@crvouga/mockingbird-service-otel 3.2.0 → 3.3.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/CHANGELOG.md +10 -4
- package/README.md +82 -9
- package/SUPPORT.md +6 -3
- package/dist/{chunk-CZKU2KT2.js → chunk-JZ6IVZNV.js} +44 -8
- package/dist/{chunk-CZKU2KT2.js.map → chunk-JZ6IVZNV.js.map} +2 -2
- package/dist/{chunk-HRGWNDT2.js → chunk-T4AU5UCQ.js} +180 -36
- package/dist/{chunk-HRGWNDT2.js.map → chunk-T4AU5UCQ.js.map} +4 -4
- package/dist/cli.js +2 -2
- package/dist/index.d.ts +56 -13
- package/dist/index.js +3 -1
- package/dist/server.d.ts +42 -2
- package/dist/server.js +2 -2
- package/openapi.yaml +311 -6
- package/package.json +1 -1
|
@@ -2189,7 +2189,7 @@ var stateAdminRoutes = (routes) => {
|
|
|
2189
2189
|
};
|
|
2190
2190
|
|
|
2191
2191
|
// ../core/dist/version.js
|
|
2192
|
-
var PACKAGE_VERSION = true ? "3.
|
|
2192
|
+
var PACKAGE_VERSION = true ? "3.3.0" : UNRELEASED_VERSION;
|
|
2193
2193
|
|
|
2194
2194
|
// ../core/dist/webhooks.js
|
|
2195
2195
|
var json4 = (status, body) => new Response(JSON.stringify(body), {
|
|
@@ -3046,10 +3046,66 @@ var presetRoutes = (presets, runtime, adminPrefix) => ({
|
|
|
3046
3046
|
}
|
|
3047
3047
|
});
|
|
3048
3048
|
|
|
3049
|
+
// src/cors.ts
|
|
3050
|
+
var DEFAULT_METHODS = ["GET", "POST", "HEAD"];
|
|
3051
|
+
var DEFAULT_HEADERS = ["accept", "content-type", "x-requested-with"];
|
|
3052
|
+
var corsEnabled = (cors) => cors.allowedOrigins.length > 0;
|
|
3053
|
+
var isPreflight = (request) => request.method === "OPTIONS" && request.headers.has("access-control-request-method");
|
|
3054
|
+
var originAllowed = (cors, origin) => {
|
|
3055
|
+
const candidate = origin.toLowerCase();
|
|
3056
|
+
return cors.allowedOrigins.some((allowed) => {
|
|
3057
|
+
const pattern = allowed.toLowerCase();
|
|
3058
|
+
const star = pattern.indexOf("*");
|
|
3059
|
+
if (star < 0) return pattern === candidate;
|
|
3060
|
+
const prefix = pattern.slice(0, star);
|
|
3061
|
+
const suffix = pattern.slice(star + 1);
|
|
3062
|
+
return candidate.length >= prefix.length + suffix.length && candidate.startsWith(prefix) && candidate.endsWith(suffix);
|
|
3063
|
+
});
|
|
3064
|
+
};
|
|
3065
|
+
var allowOrigin = (cors, origin) => cors.allowedOrigins.includes("*") ? "*" : origin;
|
|
3066
|
+
var methodAllowed = (cors, method) => {
|
|
3067
|
+
if (method === "OPTIONS") return true;
|
|
3068
|
+
const methods = cors.allowedMethods?.length ? cors.allowedMethods : DEFAULT_METHODS;
|
|
3069
|
+
return methods.some((allowed) => allowed.toUpperCase() === method);
|
|
3070
|
+
};
|
|
3071
|
+
var headersAllowed = (cors, requested) => {
|
|
3072
|
+
if (requested === null) return true;
|
|
3073
|
+
const allowed = cors.allowedHeaders?.length ? cors.allowedHeaders : DEFAULT_HEADERS;
|
|
3074
|
+
if (allowed.includes("*")) return true;
|
|
3075
|
+
const names = new Set(allowed.map((name) => name.toLowerCase()));
|
|
3076
|
+
return requested.split(",").map((name) => name.trim().toLowerCase()).every((name) => name === "" || names.has(name));
|
|
3077
|
+
};
|
|
3078
|
+
var preflightResponse = (request, cors) => {
|
|
3079
|
+
const headers = new Headers({
|
|
3080
|
+
vary: "Origin, Access-Control-Request-Method, Access-Control-Request-Headers"
|
|
3081
|
+
});
|
|
3082
|
+
const origin = request.headers.get("origin");
|
|
3083
|
+
const method = request.headers.get("access-control-request-method") ?? "";
|
|
3084
|
+
const requested = request.headers.get("access-control-request-headers");
|
|
3085
|
+
if (origin && originAllowed(cors, origin) && methodAllowed(cors, method) && headersAllowed(cors, requested)) {
|
|
3086
|
+
headers.set("access-control-allow-origin", allowOrigin(cors, origin));
|
|
3087
|
+
headers.set("access-control-allow-methods", method);
|
|
3088
|
+
if (requested) headers.set("access-control-allow-headers", requested);
|
|
3089
|
+
headers.set("access-control-allow-credentials", "true");
|
|
3090
|
+
if (cors.maxAge) headers.set("access-control-max-age", String(Math.max(0, cors.maxAge)));
|
|
3091
|
+
}
|
|
3092
|
+
return new Response(null, { status: 204, headers });
|
|
3093
|
+
};
|
|
3094
|
+
var applyCors = (request, response, cors) => {
|
|
3095
|
+
response.headers.append("vary", "Origin");
|
|
3096
|
+
const origin = request.headers.get("origin");
|
|
3097
|
+
if (!origin || !originAllowed(cors, origin) || !methodAllowed(cors, request.method)) return;
|
|
3098
|
+
response.headers.set("access-control-allow-origin", allowOrigin(cors, origin));
|
|
3099
|
+
if (cors.exposedHeaders?.length) {
|
|
3100
|
+
response.headers.set("access-control-expose-headers", cors.exposedHeaders.join(", "));
|
|
3101
|
+
}
|
|
3102
|
+
response.headers.set("access-control-allow-credentials", "true");
|
|
3103
|
+
};
|
|
3104
|
+
|
|
3049
3105
|
// src/generated/openapi.ts
|
|
3050
|
-
var document = JSON.parse(`{"openapi":"3.1.0","info":{"title":"OTLP/HTTP collector and OpenObserve search (Mockingbird subset)","description":"An OTLP/HTTP receiver (traces, logs, metrics; JSON and protobuf) in front of the\\nOpenObserve (O2) search API, over one store: a test emits a span or a structured \`event\`\\nlog and queries it back with the same SQL our clients send.\\n","version":"1","x-mockingbird-upstream":{"note":"OTLP/HTTP per opentelemetry-proto v1 (https://opentelemetry.io/docs/specs/otlp/); the O2 routes follow OpenObserve's API (/api-doc/openapi.json, v0.92) trimmed to what our clients call."}},"servers":[{"url":"https://otel.acme.example"},{"url":"https://observe.acme.example"}],"security":[{"bearerAuth":[]}],"paths":{"/v1/traces":{"post":{"operationId":"ExportTraces","summary":"OTLP/HTTP trace export (ExportTraceServiceRequest)","x-mockingbird":{"supported":true,"parity":{"enabled":true,"safe":false}},"requestBody":{"required":true,"content":{"application/json":{"schema":{"$ref":"#/components/schemas/ExportTraceServiceRequest"}},"application/x-protobuf":{"schema":{"type":"string","format":"binary"}}}},"responses":{"200":{"description":"Accepted. JSON requests get \`{partialSuccess: {}}\`; protobuf requests get an empty protobuf response.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ExportResponse"}},"application/x-protobuf":{"schema":{"type":"string","format":"binary"}}}},"400":{"description":"Undecodable payload","content":{"application/json":{"schema":{"$ref":"#/components/schemas/RpcStatus"}}}},"401":{"description":"Missing or unknown bearer token","content":{"application/json":{"schema":{"$ref":"#/components/schemas/RpcStatus"}}}},"415":{"description":"Neither application/json nor application/x-protobuf","content":{"application/json":{"schema":{"$ref":"#/components/schemas/RpcStatus"}}}},"429":{"description":"Throttled (retried by the SDK), with retry-after","headers":{"retry-after":{"schema":{"type":"string"}}},"content":{"application/json":{"schema":{"$ref":"#/components/schemas/RpcStatus"}}}},"500":{"description":"Collector error (not retried by the SDK)","content":{"application/json":{"schema":{"$ref":"#/components/schemas/RpcStatus"}}}},"502":{"description":"Bad gateway (retried)","content":{"application/json":{"schema":{"$ref":"#/components/schemas/RpcStatus"}}}},"503":{"description":"Unavailable (retried)","content":{"application/json":{"schema":{"$ref":"#/components/schemas/RpcStatus"}}}},"504":{"description":"Gateway timeout (retried)","content":{"application/json":{"schema":{"$ref":"#/components/schemas/RpcStatus"}}}}}}},"/v1/logs":{"post":{"operationId":"ExportLogs","summary":"OTLP/HTTP log export (ExportLogsServiceRequest)","x-mockingbird":{"supported":true,"parity":{"enabled":true,"safe":false}},"requestBody":{"required":true,"content":{"application/json":{"schema":{"$ref":"#/components/schemas/ExportLogsServiceRequest"}},"application/x-protobuf":{"schema":{"type":"string","format":"binary"}}}},"responses":{"200":{"description":"Accepted. JSON requests get \`{partialSuccess: {}}\`; protobuf requests get an empty protobuf response.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ExportResponse"}},"application/x-protobuf":{"schema":{"type":"string","format":"binary"}}}},"400":{"description":"Undecodable payload","content":{"application/json":{"schema":{"$ref":"#/components/schemas/RpcStatus"}}}},"401":{"description":"Missing or unknown bearer token","content":{"application/json":{"schema":{"$ref":"#/components/schemas/RpcStatus"}}}},"415":{"description":"Neither application/json nor application/x-protobuf","content":{"application/json":{"schema":{"$ref":"#/components/schemas/RpcStatus"}}}},"429":{"description":"Throttled (retried by the SDK), with retry-after","headers":{"retry-after":{"schema":{"type":"string"}}},"content":{"application/json":{"schema":{"$ref":"#/components/schemas/RpcStatus"}}}},"500":{"description":"Collector error (not retried by the SDK)","content":{"application/json":{"schema":{"$ref":"#/components/schemas/RpcStatus"}}}},"502":{"description":"Bad gateway (retried)","content":{"application/json":{"schema":{"$ref":"#/components/schemas/RpcStatus"}}}},"503":{"description":"Unavailable (retried)","content":{"application/json":{"schema":{"$ref":"#/components/schemas/RpcStatus"}}}},"504":{"description":"Gateway timeout (retried)","content":{"application/json":{"schema":{"$ref":"#/components/schemas/RpcStatus"}}}}}}},"/v1/metrics":{"post":{"operationId":"ExportMetrics","summary":"OTLP/HTTP metrics export: accepted and counted, never stored","x-mockingbird":{"supported":true,"parity":{"enabled":true,"safe":false}},"requestBody":{"required":true,"content":{"application/json":{"schema":{"$ref":"#/components/schemas/ExportMetricsServiceRequest"}},"application/x-protobuf":{"schema":{"type":"string","format":"binary"}}}},"responses":{"200":{"description":"Accepted. JSON requests get \`{partialSuccess: {}}\`; protobuf requests get an empty protobuf response.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ExportResponse"}},"application/x-protobuf":{"schema":{"type":"string","format":"binary"}}}},"400":{"description":"Undecodable payload","content":{"application/json":{"schema":{"$ref":"#/components/schemas/RpcStatus"}}}},"401":{"description":"Missing or unknown bearer token","content":{"application/json":{"schema":{"$ref":"#/components/schemas/RpcStatus"}}}},"415":{"description":"Neither application/json nor application/x-protobuf","content":{"application/json":{"schema":{"$ref":"#/components/schemas/RpcStatus"}}}},"429":{"description":"Throttled (retried by the SDK), with retry-after","headers":{"retry-after":{"schema":{"type":"string"}}},"content":{"application/json":{"schema":{"$ref":"#/components/schemas/RpcStatus"}}}},"500":{"description":"Collector error (not retried by the SDK)","content":{"application/json":{"schema":{"$ref":"#/components/schemas/RpcStatus"}}}},"502":{"description":"Bad gateway (retried)","content":{"application/json":{"schema":{"$ref":"#/components/schemas/RpcStatus"}}}},"503":{"description":"Unavailable (retried)","content":{"application/json":{"schema":{"$ref":"#/components/schemas/RpcStatus"}}}},"504":{"description":"Gateway timeout (retried)","content":{"application/json":{"schema":{"$ref":"#/components/schemas/RpcStatus"}}}}}}},"/api/organizations":{"get":{"operationId":"ListOrganizations","summary":"O2: the organizations the Basic user belongs to (display name \u2192 identifier)","security":[{"basicAuth":[]}],"x-mockingbird":{"supported":true,"parity":{"enabled":true,"safe":true}},"responses":{"200":{"description":"Organizations","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Organizations"}}}},"401":{"description":"Bad Basic credentials, or an org the user cannot see \u2014 including an org's display name in place of its identifier","content":{"text/plain":{"schema":{"type":"string"}}}}}}},"/api/{org}/streams":{"parameters":[{"name":"org","in":"path","required":true,"description":"The org **identifier** (not its display name)","schema":{"type":"string","x-mockingbird-resource-ref":{"type":"organization","missing":"no-such-org"}}}],"get":{"operationId":"ListStreams","summary":"O2: the org's streams of one type","security":[{"basicAuth":[]}],"x-mockingbird":{"supported":true,"parity":{"enabled":true,"safe":true}},"parameters":[{"name":"type","in":"query","required":false,"schema":{"type":"string","enum":["logs","traces"]}}],"responses":{"200":{"description":"Streams","content":{"application/json":{"schema":{"$ref":"#/components/schemas/StreamList"}}}},"401":{"description":"Bad Basic credentials, or an org the user cannot see \u2014 including an org's display name in place of its identifier","content":{"text/plain":{"schema":{"type":"string"}}}}}}},"/api/{org}/streams/{stream}/schema":{"parameters":[{"name":"org","in":"path","required":true,"description":"The org **identifier** (not its display name)","schema":{"type":"string","x-mockingbird-resource-ref":{"type":"organization","missing":"no-such-org"}}},{"name":"stream","in":"path","required":true,"schema":{"type":"string","enum":["default","other"]}}],"get":{"operationId":"GetStreamSchema","summary":"O2: a stream's schema (\`schema[].name\` are the queryable, lowercased, flattened fields)","security":[{"basicAuth":[]}],"x-mockingbird":{"supported":true,"parity":{"enabled":true,"safe":true}},"parameters":[{"name":"type","in":"query","required":false,"schema":{"type":"string","enum":["logs","traces"]}}],"responses":{"200":{"description":"Schema","content":{"application/json":{"schema":{"$ref":"#/components/schemas/StreamSchema"}}}},"401":{"description":"Bad Basic credentials, or an org the user cannot see \u2014 including an org's display name in place of its identifier","content":{"text/plain":{"schema":{"type":"string"}}}},"404":{"description":"Nothing has been ingested into this stream","content":{"application/json":{"schema":{"$ref":"#/components/schemas/O2Error"}}}}}}},"/api/{org}/_search":{"parameters":[{"name":"org","in":"path","required":true,"description":"The org **identifier** (not its display name)","schema":{"type":"string","x-mockingbird-resource-ref":{"type":"organization","missing":"no-such-org"}}}],"post":{"operationId":"Search","summary":"O2: SQL search over a stream","security":[{"basicAuth":[]}],"x-mockingbird":{"supported":true,"parity":{"enabled":true,"safe":true}},"parameters":[{"name":"type","in":"query","required":false,"schema":{"type":"string","enum":["logs","traces"]}}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"type":"object","required":["query"],"properties":{"query":{"type":"object","required":["sql"],"properties":{"sql":{"anyOf":[{"type":"string","enum":["SELECT * FROM \\"default\\" WHERE event IS NOT NULL ORDER BY _timestamp DESC","SELECT * FROM \\"default\\" WHERE event IN ('checkout_completed') ORDER BY _timestamp DESC","SELECT service_name, count(*) AS n FROM \\"default\\" GROUP BY service_name ORDER BY n DESC","SELECT * FROM \\"default\\" WHERE severity_text IN ('ERROR', 'FATAL')","SELECT * FROM \\"default\\" WHERE clientUserId = '1'"]},{"type":"string","maxLength":200}]},"start_time":{"type":"integer","minimum":0,"description":"\xB5s since epoch"},"end_time":{"type":"integer","minimum":0,"description":"\xB5s since epoch"},"from":{"type":"integer","minimum":0,"maximum":100},"size":{"type":"integer","minimum":-1,"maximum":1000}}},"search_type":{"type":"string","maxLength":20}}}}}},"responses":{"200":{"description":"Hits","content":{"application/json":{"schema":{"$ref":"#/components/schemas/SearchResponse"}}}},"400":{"description":"Unsupported SQL, or an unknown field (O2 lowercases every field; a camelCase column is unknown)","content":{"application/json":{"schema":{"$ref":"#/components/schemas/O2Error"}}}},"401":{"description":"Bad Basic credentials, or an org the user cannot see \u2014 including an org's display name in place of its identifier","content":{"text/plain":{"schema":{"type":"string"}}}}}}}},"components":{"securitySchemes":{"bearerAuth":{"type":"http","scheme":"bearer"},"basicAuth":{"type":"http","scheme":"basic"}},"schemas":{"KeyValue":{"type":"object","required":["key","value"],"properties":{"key":{"type":"string","enum":["service.name","event","clientUserId","http.method","deployment.environment.name","attempt"]},"value":{"type":"object","properties":{"stringValue":{"type":"string","maxLength":20},"intValue":{"type":["string","integer"]},"boolValue":{"type":"boolean"},"doubleValue":{"type":"number"}}}}},"ExportTraceServiceRequest":{"type":"object","properties":{"resourceSpans":{"type":"array","maxItems":2,"items":{"type":"object","properties":{"resource":{"type":"object","properties":{"attributes":{"type":"array","maxItems":4,"items":{"$ref":"#/components/schemas/KeyValue"}}}},"scopeSpans":{"type":"array","maxItems":2,"items":{"type":"object","properties":{"scope":{"type":"object","properties":{"name":{"type":"string","maxLength":20}}},"spans":{"type":"array","maxItems":3,"items":{"type":"object","required":["traceId","spanId","name"],"properties":{"traceId":{"type":"string","pattern":"^[0-9a-f]{32}$"},"spanId":{"type":"string","pattern":"^[0-9a-f]{16}$"},"parentSpanId":{"type":"string","pattern":"^[0-9a-f]{16}$"},"name":{"type":"string","maxLength":30},"kind":{"type":"integer","minimum":0,"maximum":5},"startTimeUnixNano":{"type":"string","pattern":"^1[0-9]{18}$"},"endTimeUnixNano":{"type":"string","pattern":"^1[0-9]{18}$"},"attributes":{"type":"array","maxItems":4,"items":{"$ref":"#/components/schemas/KeyValue"}},"status":{"type":"object","properties":{"code":{"type":"integer","minimum":0,"maximum":2},"message":{"type":"string","maxLength":40}}}}}}}}}}}}}},"ExportLogsServiceRequest":{"type":"object","properties":{"resourceLogs":{"type":"array","maxItems":2,"items":{"type":"object","properties":{"resource":{"type":"object","properties":{"attributes":{"type":"array","maxItems":4,"items":{"$ref":"#/components/schemas/KeyValue"}}}},"scopeLogs":{"type":"array","maxItems":2,"items":{"type":"object","properties":{"scope":{"type":"object","properties":{"name":{"type":"string","maxLength":20}}},"logRecords":{"type":"array","maxItems":3,"items":{"type":"object","properties":{"timeUnixNano":{"type":"string","pattern":"^1[0-9]{18}$"},"observedTimeUnixNano":{"type":"string","pattern":"^1[0-9]{18}$"},"severityNumber":{"type":"integer","minimum":0,"maximum":24},"severityText":{"type":"string","enum":["TRACE","DEBUG","INFO","WARN","ERROR","FATAL","info","error"]},"body":{"type":"object","properties":{"stringValue":{"type":"string","maxLength":40}}},"attributes":{"type":"array","maxItems":4,"items":{"$ref":"#/components/schemas/KeyValue"}},"traceId":{"type":"string","pattern":"^[0-9a-f]{32}$"},"spanId":{"type":"string","pattern":"^[0-9a-f]{16}$"}}}}}}}}}}}},"ExportMetricsServiceRequest":{"type":"object","properties":{"resourceMetrics":{"type":"array","maxItems":2,"items":{"type":"object","properties":{"resource":{"type":"object","properties":{"attributes":{"type":"array","maxItems":4,"items":{"$ref":"#/components/schemas/KeyValue"}}}},"scopeMetrics":{"type":"array","maxItems":2,"items":{"type":"object","properties":{"metrics":{"type":"array","maxItems":3,"items":{"type":"object","properties":{"name":{"type":"string","maxLength":30},"unit":{"type":"string","maxLength":10}}}}}}}}}}}},"ExportResponse":{"type":"object","required":["partialSuccess"],"properties":{"partialSuccess":{"type":"object","properties":{"rejectedSpans":{"type":["string","integer"]},"rejectedLogRecords":{"type":["string","integer"]},"rejectedDataPoints":{"type":["string","integer"]},"errorMessage":{"type":"string"}}}}},"RpcStatus":{"type":"object","required":["code","message"],"properties":{"code":{"type":"integer"},"message":{"type":"string"}}},"O2Error":{"type":"object","required":["code","message"],"properties":{"code":{"type":"integer"},"message":{"type":"string"},"error_detail":{"type":"string"}}},"Organizations":{"type":"object","required":["data"],"properties":{"data":{"type":"array","items":{"type":"object","required":["identifier","name"],"properties":{"id":{"type":"integer"},"identifier":{"type":"string","x-mockingbird-resource":{"type":"organization","identity":true}},"name":{"type":"string"},"type":{"type":"string"}}}}}},"StreamList":{"type":"object","required":["list"],"properties":{"list":{"type":"array","items":{"type":"object","required":["name","stream_type"],"properties":{"name":{"type":"string"},"stream_type":{"type":"string"},"storage_type":{"type":"string"},"stats":{"type":"object"}}}}}},"StreamSchema":{"type":"object","required":["name","stream_type","schema"],"properties":{"name":{"type":"string"},"stream_type":{"type":"string"},"storage_type":{"type":"string"},"stats":{"type":"object"},"schema":{"type":"array","items":{"type":"object","required":["name","type"],"properties":{"name":{"type":"string"},"type":{"type":"string","enum":["Utf8","Int64","Float64","Boolean"]}}}},"settings":{"type":"object"}}},"SearchResponse":{"type":"object","required":["took","hits","total","from","size"],"properties":{"took":{"type":"integer","x-mockingbird-volatile":{"kind":"opaque"}},"hits":{"type":"array","items":{"type":"object"}},"total":{"type":"integer"},"from":{"type":"integer"},"size":{"type":"integer"},"scan_size":{"type":"integer"},"scan_records":{"type":"integer"},"is_partial":{"type":"boolean"},"cached_ratio":{"type":"integer"}}}}}}`);
|
|
3051
|
-
var operationIds = ["ExportTraces", "ExportLogs", "ExportMetrics", "ListOrganizations", "ListStreams", "GetStreamSchema", "Search"];
|
|
3052
|
-
var supportedOperationIds = ["ExportTraces", "ExportLogs", "ExportMetrics", "ListOrganizations", "ListStreams", "GetStreamSchema", "Search"];
|
|
3106
|
+
var document = JSON.parse(`{"openapi":"3.1.0","info":{"title":"OTLP/HTTP collector and OpenObserve search (Mockingbird subset)","description":"An OTLP/HTTP receiver (traces, logs, metrics; JSON and protobuf) in front of the\\nOpenObserve (O2) search API, over one store: a test emits a span or a structured \`event\`\\nlog and queries it back with the same SQL our clients send.\\n\\nThe receiver authenticates exports the way the collector it stands in for does, chosen by\\nthe \`ingestAuth\` setting: \`bearer\` (the default), \`basic\` (a hosted OTLP gateway's\\n\`Authorization: Basic base64(instanceId:token)\`) or \`none\` (a local collector). With\\n\`cors.allowedOrigins\` set it also answers a browser exporter's CORS preflight.\\n","version":"1","x-mockingbird-upstream":{"note":"OTLP/HTTP per opentelemetry-proto v1 (https://opentelemetry.io/docs/specs/otlp/); the O2 routes follow OpenObserve's API (/api-doc/openapi.json, v0.92) trimmed to what our clients call."}},"servers":[{"url":"https://otel.acme.example"},{"url":"https://observe.acme.example"}],"security":[{"bearerAuth":[]}],"paths":{"/v1/traces":{"post":{"operationId":"ExportTraces","summary":"OTLP/HTTP trace export (ExportTraceServiceRequest)","security":[{"bearerAuth":[]},{"basicAuth":[]},{}],"x-mockingbird":{"supported":true,"parity":{"enabled":true,"safe":false}},"requestBody":{"required":true,"content":{"application/json":{"schema":{"$ref":"#/components/schemas/ExportTraceServiceRequest"}},"application/x-protobuf":{"schema":{"type":"string","format":"binary"}}}},"responses":{"200":{"description":"Accepted. JSON requests get \`{partialSuccess: {}}\`; protobuf requests get an empty protobuf response.","headers":{"access-control-allow-origin":{"description":"With CORS on, the request's \`Origin\` when it is allowed (\`*\` when any origin is). Sent on every status, errors included.","schema":{"type":"string"}},"access-control-allow-credentials":{"description":"\`true\`, beside \`access-control-allow-origin\`","schema":{"type":"string"}},"access-control-expose-headers":{"description":"The configured \`cors.exposedHeaders\`","schema":{"type":"string"}},"vary":{"description":"\`Origin\`, whenever CORS is on","schema":{"type":"string"}}},"content":{"application/json":{"schema":{"$ref":"#/components/schemas/ExportResponse"}},"application/x-protobuf":{"schema":{"type":"string","format":"binary"}}}},"400":{"description":"Undecodable payload. Like every receiver error it is a \`google.rpc.Status\` in the request's encoding (binary for protobuf requests, JSON otherwise).","content":{"application/json":{"schema":{"$ref":"#/components/schemas/RpcStatus"}},"application/x-protobuf":{"schema":{"type":"string","format":"binary"}}}},"401":{"description":"Credentials missing or not accepted for the \`ingestAuth\` mode: a bearer token (\`bearer\`, the default) or Basic credentials (\`basic\`). \`none\` mode refuses nothing.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/RpcStatus"}},"application/x-protobuf":{"schema":{"type":"string","format":"binary"}}}},"415":{"description":"Neither application/json nor application/x-protobuf","content":{"application/json":{"schema":{"$ref":"#/components/schemas/RpcStatus"}}}},"429":{"description":"Throttled (retried by the SDK), with retry-after","headers":{"retry-after":{"schema":{"type":"string"}}},"content":{"application/json":{"schema":{"$ref":"#/components/schemas/RpcStatus"}}}},"500":{"description":"Collector error (not retried by the SDK)","content":{"application/json":{"schema":{"$ref":"#/components/schemas/RpcStatus"}}}},"502":{"description":"Bad gateway (retried)","content":{"application/json":{"schema":{"$ref":"#/components/schemas/RpcStatus"}}}},"503":{"description":"Unavailable (retried)","content":{"application/json":{"schema":{"$ref":"#/components/schemas/RpcStatus"}}}},"504":{"description":"Gateway timeout (retried)","content":{"application/json":{"schema":{"$ref":"#/components/schemas/RpcStatus"}}}}}},"options":{"operationId":"PreflightTraces","summary":"CORS preflight a browser exporter sends before \`POST /v1/traces\`","description":"Answered only when \`cors.allowedOrigins\` is set, and before authentication (a preflight carries no credentials). A refused preflight is the same 204 without the \`access-control-allow-*\` headers.","security":[],"x-mockingbird":{"supported":true,"parity":{"enabled":true,"safe":true}},"parameters":[{"name":"Origin","in":"header","required":false,"schema":{"type":"string","enum":["https://app.example.test"]}},{"name":"Access-Control-Request-Method","in":"header","required":false,"schema":{"type":"string","enum":["POST"]}},{"name":"Access-Control-Request-Headers","in":"header","required":false,"schema":{"type":"string","enum":["content-type","authorization,content-type,traceparent,tracestate"]}}],"responses":{"204":{"description":"Preflight answered. The \`access-control-allow-*\` headers are present only when the origin, the requested method and every requested header are allowed.","headers":{"access-control-allow-origin":{"description":"The request's \`Origin\` (\`*\` when any origin is allowed)","schema":{"type":"string"}},"access-control-allow-methods":{"description":"The requested method","schema":{"type":"string"}},"access-control-allow-headers":{"description":"The requested headers","schema":{"type":"string"}},"access-control-allow-credentials":{"schema":{"type":"string"}},"access-control-max-age":{"description":"The configured \`cors.maxAge\`, in seconds","schema":{"type":"string"}},"vary":{"schema":{"type":"string"}}}},"405":{"description":"CORS is off (no allowed origin), or the request names no \`Access-Control-Request-Method\`","content":{"text/plain":{"schema":{"type":"string"}}}}}}},"/v1/logs":{"post":{"operationId":"ExportLogs","summary":"OTLP/HTTP log export (ExportLogsServiceRequest)","security":[{"bearerAuth":[]},{"basicAuth":[]},{}],"x-mockingbird":{"supported":true,"parity":{"enabled":true,"safe":false}},"requestBody":{"required":true,"content":{"application/json":{"schema":{"$ref":"#/components/schemas/ExportLogsServiceRequest"}},"application/x-protobuf":{"schema":{"type":"string","format":"binary"}}}},"responses":{"200":{"description":"Accepted. JSON requests get \`{partialSuccess: {}}\`; protobuf requests get an empty protobuf response.","headers":{"access-control-allow-origin":{"description":"With CORS on, the request's \`Origin\` when it is allowed (\`*\` when any origin is). Sent on every status, errors included.","schema":{"type":"string"}},"access-control-allow-credentials":{"description":"\`true\`, beside \`access-control-allow-origin\`","schema":{"type":"string"}},"access-control-expose-headers":{"description":"The configured \`cors.exposedHeaders\`","schema":{"type":"string"}},"vary":{"description":"\`Origin\`, whenever CORS is on","schema":{"type":"string"}}},"content":{"application/json":{"schema":{"$ref":"#/components/schemas/ExportResponse"}},"application/x-protobuf":{"schema":{"type":"string","format":"binary"}}}},"400":{"description":"Undecodable payload. Like every receiver error it is a \`google.rpc.Status\` in the request's encoding (binary for protobuf requests, JSON otherwise).","content":{"application/json":{"schema":{"$ref":"#/components/schemas/RpcStatus"}},"application/x-protobuf":{"schema":{"type":"string","format":"binary"}}}},"401":{"description":"Credentials missing or not accepted for the \`ingestAuth\` mode: a bearer token (\`bearer\`, the default) or Basic credentials (\`basic\`). \`none\` mode refuses nothing.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/RpcStatus"}},"application/x-protobuf":{"schema":{"type":"string","format":"binary"}}}},"415":{"description":"Neither application/json nor application/x-protobuf","content":{"application/json":{"schema":{"$ref":"#/components/schemas/RpcStatus"}}}},"429":{"description":"Throttled (retried by the SDK), with retry-after","headers":{"retry-after":{"schema":{"type":"string"}}},"content":{"application/json":{"schema":{"$ref":"#/components/schemas/RpcStatus"}}}},"500":{"description":"Collector error (not retried by the SDK)","content":{"application/json":{"schema":{"$ref":"#/components/schemas/RpcStatus"}}}},"502":{"description":"Bad gateway (retried)","content":{"application/json":{"schema":{"$ref":"#/components/schemas/RpcStatus"}}}},"503":{"description":"Unavailable (retried)","content":{"application/json":{"schema":{"$ref":"#/components/schemas/RpcStatus"}}}},"504":{"description":"Gateway timeout (retried)","content":{"application/json":{"schema":{"$ref":"#/components/schemas/RpcStatus"}}}}}},"options":{"operationId":"PreflightLogs","summary":"CORS preflight a browser exporter sends before \`POST /v1/logs\`","description":"Answered only when \`cors.allowedOrigins\` is set, and before authentication (a preflight carries no credentials). A refused preflight is the same 204 without the \`access-control-allow-*\` headers.","security":[],"x-mockingbird":{"supported":true,"parity":{"enabled":true,"safe":true}},"parameters":[{"name":"Origin","in":"header","required":false,"schema":{"type":"string","enum":["https://app.example.test"]}},{"name":"Access-Control-Request-Method","in":"header","required":false,"schema":{"type":"string","enum":["POST"]}},{"name":"Access-Control-Request-Headers","in":"header","required":false,"schema":{"type":"string","enum":["content-type","authorization,content-type,traceparent,tracestate"]}}],"responses":{"204":{"description":"Preflight answered. The \`access-control-allow-*\` headers are present only when the origin, the requested method and every requested header are allowed.","headers":{"access-control-allow-origin":{"description":"The request's \`Origin\` (\`*\` when any origin is allowed)","schema":{"type":"string"}},"access-control-allow-methods":{"description":"The requested method","schema":{"type":"string"}},"access-control-allow-headers":{"description":"The requested headers","schema":{"type":"string"}},"access-control-allow-credentials":{"schema":{"type":"string"}},"access-control-max-age":{"description":"The configured \`cors.maxAge\`, in seconds","schema":{"type":"string"}},"vary":{"schema":{"type":"string"}}}},"405":{"description":"CORS is off (no allowed origin), or the request names no \`Access-Control-Request-Method\`","content":{"text/plain":{"schema":{"type":"string"}}}}}}},"/v1/metrics":{"post":{"operationId":"ExportMetrics","summary":"OTLP/HTTP metrics export: accepted and counted, never stored","security":[{"bearerAuth":[]},{"basicAuth":[]},{}],"x-mockingbird":{"supported":true,"parity":{"enabled":true,"safe":false}},"requestBody":{"required":true,"content":{"application/json":{"schema":{"$ref":"#/components/schemas/ExportMetricsServiceRequest"}},"application/x-protobuf":{"schema":{"type":"string","format":"binary"}}}},"responses":{"200":{"description":"Accepted. JSON requests get \`{partialSuccess: {}}\`; protobuf requests get an empty protobuf response.","headers":{"access-control-allow-origin":{"description":"With CORS on, the request's \`Origin\` when it is allowed (\`*\` when any origin is). Sent on every status, errors included.","schema":{"type":"string"}},"access-control-allow-credentials":{"description":"\`true\`, beside \`access-control-allow-origin\`","schema":{"type":"string"}},"access-control-expose-headers":{"description":"The configured \`cors.exposedHeaders\`","schema":{"type":"string"}},"vary":{"description":"\`Origin\`, whenever CORS is on","schema":{"type":"string"}}},"content":{"application/json":{"schema":{"$ref":"#/components/schemas/ExportResponse"}},"application/x-protobuf":{"schema":{"type":"string","format":"binary"}}}},"400":{"description":"Undecodable payload. Like every receiver error it is a \`google.rpc.Status\` in the request's encoding (binary for protobuf requests, JSON otherwise).","content":{"application/json":{"schema":{"$ref":"#/components/schemas/RpcStatus"}},"application/x-protobuf":{"schema":{"type":"string","format":"binary"}}}},"401":{"description":"Credentials missing or not accepted for the \`ingestAuth\` mode: a bearer token (\`bearer\`, the default) or Basic credentials (\`basic\`). \`none\` mode refuses nothing.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/RpcStatus"}},"application/x-protobuf":{"schema":{"type":"string","format":"binary"}}}},"415":{"description":"Neither application/json nor application/x-protobuf","content":{"application/json":{"schema":{"$ref":"#/components/schemas/RpcStatus"}}}},"429":{"description":"Throttled (retried by the SDK), with retry-after","headers":{"retry-after":{"schema":{"type":"string"}}},"content":{"application/json":{"schema":{"$ref":"#/components/schemas/RpcStatus"}}}},"500":{"description":"Collector error (not retried by the SDK)","content":{"application/json":{"schema":{"$ref":"#/components/schemas/RpcStatus"}}}},"502":{"description":"Bad gateway (retried)","content":{"application/json":{"schema":{"$ref":"#/components/schemas/RpcStatus"}}}},"503":{"description":"Unavailable (retried)","content":{"application/json":{"schema":{"$ref":"#/components/schemas/RpcStatus"}}}},"504":{"description":"Gateway timeout (retried)","content":{"application/json":{"schema":{"$ref":"#/components/schemas/RpcStatus"}}}}}},"options":{"operationId":"PreflightMetrics","summary":"CORS preflight a browser exporter sends before \`POST /v1/metrics\`","description":"Answered only when \`cors.allowedOrigins\` is set, and before authentication (a preflight carries no credentials). A refused preflight is the same 204 without the \`access-control-allow-*\` headers.","security":[],"x-mockingbird":{"supported":true,"parity":{"enabled":true,"safe":true}},"parameters":[{"name":"Origin","in":"header","required":false,"schema":{"type":"string","enum":["https://app.example.test"]}},{"name":"Access-Control-Request-Method","in":"header","required":false,"schema":{"type":"string","enum":["POST"]}},{"name":"Access-Control-Request-Headers","in":"header","required":false,"schema":{"type":"string","enum":["content-type","authorization,content-type,traceparent,tracestate"]}}],"responses":{"204":{"description":"Preflight answered. The \`access-control-allow-*\` headers are present only when the origin, the requested method and every requested header are allowed.","headers":{"access-control-allow-origin":{"description":"The request's \`Origin\` (\`*\` when any origin is allowed)","schema":{"type":"string"}},"access-control-allow-methods":{"description":"The requested method","schema":{"type":"string"}},"access-control-allow-headers":{"description":"The requested headers","schema":{"type":"string"}},"access-control-allow-credentials":{"schema":{"type":"string"}},"access-control-max-age":{"description":"The configured \`cors.maxAge\`, in seconds","schema":{"type":"string"}},"vary":{"schema":{"type":"string"}}}},"405":{"description":"CORS is off (no allowed origin), or the request names no \`Access-Control-Request-Method\`","content":{"text/plain":{"schema":{"type":"string"}}}}}}},"/api/organizations":{"get":{"operationId":"ListOrganizations","summary":"O2: the organizations the Basic user belongs to (display name \u2192 identifier)","security":[{"basicAuth":[]}],"x-mockingbird":{"supported":true,"parity":{"enabled":true,"safe":true}},"responses":{"200":{"description":"Organizations","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Organizations"}}}},"401":{"description":"Bad Basic credentials, or an org the user cannot see \u2014 including an org's display name in place of its identifier","content":{"text/plain":{"schema":{"type":"string"}}}}}}},"/api/{org}/streams":{"parameters":[{"name":"org","in":"path","required":true,"description":"The org **identifier** (not its display name)","schema":{"type":"string","x-mockingbird-resource-ref":{"type":"organization","missing":"no-such-org"}}}],"get":{"operationId":"ListStreams","summary":"O2: the org's streams of one type","security":[{"basicAuth":[]}],"x-mockingbird":{"supported":true,"parity":{"enabled":true,"safe":true}},"parameters":[{"name":"type","in":"query","required":false,"schema":{"type":"string","enum":["logs","traces"]}}],"responses":{"200":{"description":"Streams","content":{"application/json":{"schema":{"$ref":"#/components/schemas/StreamList"}}}},"401":{"description":"Bad Basic credentials, or an org the user cannot see \u2014 including an org's display name in place of its identifier","content":{"text/plain":{"schema":{"type":"string"}}}}}}},"/api/{org}/streams/{stream}/schema":{"parameters":[{"name":"org","in":"path","required":true,"description":"The org **identifier** (not its display name)","schema":{"type":"string","x-mockingbird-resource-ref":{"type":"organization","missing":"no-such-org"}}},{"name":"stream","in":"path","required":true,"schema":{"type":"string","enum":["default","other"]}}],"get":{"operationId":"GetStreamSchema","summary":"O2: a stream's schema (\`schema[].name\` are the queryable, lowercased, flattened fields)","security":[{"basicAuth":[]}],"x-mockingbird":{"supported":true,"parity":{"enabled":true,"safe":true}},"parameters":[{"name":"type","in":"query","required":false,"schema":{"type":"string","enum":["logs","traces"]}}],"responses":{"200":{"description":"Schema","content":{"application/json":{"schema":{"$ref":"#/components/schemas/StreamSchema"}}}},"401":{"description":"Bad Basic credentials, or an org the user cannot see \u2014 including an org's display name in place of its identifier","content":{"text/plain":{"schema":{"type":"string"}}}},"404":{"description":"Nothing has been ingested into this stream","content":{"application/json":{"schema":{"$ref":"#/components/schemas/O2Error"}}}}}}},"/api/{org}/_search":{"parameters":[{"name":"org","in":"path","required":true,"description":"The org **identifier** (not its display name)","schema":{"type":"string","x-mockingbird-resource-ref":{"type":"organization","missing":"no-such-org"}}}],"post":{"operationId":"Search","summary":"O2: SQL search over a stream","security":[{"basicAuth":[]}],"x-mockingbird":{"supported":true,"parity":{"enabled":true,"safe":true}},"parameters":[{"name":"type","in":"query","required":false,"schema":{"type":"string","enum":["logs","traces"]}}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"type":"object","required":["query"],"properties":{"query":{"type":"object","required":["sql"],"properties":{"sql":{"anyOf":[{"type":"string","enum":["SELECT * FROM \\"default\\" WHERE event IS NOT NULL ORDER BY _timestamp DESC","SELECT * FROM \\"default\\" WHERE event IN ('checkout_completed') ORDER BY _timestamp DESC","SELECT service_name, count(*) AS n FROM \\"default\\" GROUP BY service_name ORDER BY n DESC","SELECT * FROM \\"default\\" WHERE severity_text IN ('ERROR', 'FATAL')","SELECT * FROM \\"default\\" WHERE clientUserId = '1'"]},{"type":"string","maxLength":200}]},"start_time":{"type":"integer","minimum":0,"description":"\xB5s since epoch"},"end_time":{"type":"integer","minimum":0,"description":"\xB5s since epoch"},"from":{"type":"integer","minimum":0,"maximum":100},"size":{"type":"integer","minimum":-1,"maximum":1000}}},"search_type":{"type":"string","maxLength":20}}}}}},"responses":{"200":{"description":"Hits","content":{"application/json":{"schema":{"$ref":"#/components/schemas/SearchResponse"}}}},"400":{"description":"Unsupported SQL, or an unknown field (O2 lowercases every field; a camelCase column is unknown)","content":{"application/json":{"schema":{"$ref":"#/components/schemas/O2Error"}}}},"401":{"description":"Bad Basic credentials, or an org the user cannot see \u2014 including an org's display name in place of its identifier","content":{"text/plain":{"schema":{"type":"string"}}}}}}}},"components":{"securitySchemes":{"bearerAuth":{"type":"http","scheme":"bearer"},"basicAuth":{"type":"http","scheme":"basic"}},"schemas":{"KeyValue":{"type":"object","required":["key","value"],"properties":{"key":{"type":"string","enum":["service.name","event","clientUserId","http.method","deployment.environment.name","attempt"]},"value":{"type":"object","properties":{"stringValue":{"type":"string","maxLength":20},"intValue":{"type":["string","integer"]},"boolValue":{"type":"boolean"},"doubleValue":{"type":"number"}}}}},"ExportTraceServiceRequest":{"type":"object","properties":{"resourceSpans":{"type":"array","maxItems":2,"items":{"type":"object","properties":{"resource":{"type":"object","properties":{"attributes":{"type":"array","maxItems":4,"items":{"$ref":"#/components/schemas/KeyValue"}}}},"scopeSpans":{"type":"array","maxItems":2,"items":{"type":"object","properties":{"scope":{"type":"object","properties":{"name":{"type":"string","maxLength":20}}},"spans":{"type":"array","maxItems":3,"items":{"type":"object","required":["traceId","spanId","name"],"properties":{"traceId":{"type":"string","pattern":"^[0-9a-f]{32}$"},"spanId":{"type":"string","pattern":"^[0-9a-f]{16}$"},"parentSpanId":{"type":"string","pattern":"^[0-9a-f]{16}$"},"name":{"type":"string","maxLength":30},"kind":{"type":"integer","minimum":0,"maximum":5},"startTimeUnixNano":{"type":"string","pattern":"^1[0-9]{18}$"},"endTimeUnixNano":{"type":"string","pattern":"^1[0-9]{18}$"},"attributes":{"type":"array","maxItems":4,"items":{"$ref":"#/components/schemas/KeyValue"}},"status":{"type":"object","properties":{"code":{"type":"integer","minimum":0,"maximum":2},"message":{"type":"string","maxLength":40}}}}}}}}}}}}}},"ExportLogsServiceRequest":{"type":"object","properties":{"resourceLogs":{"type":"array","maxItems":2,"items":{"type":"object","properties":{"resource":{"type":"object","properties":{"attributes":{"type":"array","maxItems":4,"items":{"$ref":"#/components/schemas/KeyValue"}}}},"scopeLogs":{"type":"array","maxItems":2,"items":{"type":"object","properties":{"scope":{"type":"object","properties":{"name":{"type":"string","maxLength":20}}},"logRecords":{"type":"array","maxItems":3,"items":{"type":"object","properties":{"timeUnixNano":{"type":"string","pattern":"^1[0-9]{18}$"},"observedTimeUnixNano":{"type":"string","pattern":"^1[0-9]{18}$"},"severityNumber":{"type":"integer","minimum":0,"maximum":24},"severityText":{"type":"string","enum":["TRACE","DEBUG","INFO","WARN","ERROR","FATAL","info","error"]},"body":{"type":"object","properties":{"stringValue":{"type":"string","maxLength":40}}},"attributes":{"type":"array","maxItems":4,"items":{"$ref":"#/components/schemas/KeyValue"}},"traceId":{"type":"string","pattern":"^[0-9a-f]{32}$"},"spanId":{"type":"string","pattern":"^[0-9a-f]{16}$"}}}}}}}}}}}},"ExportMetricsServiceRequest":{"type":"object","properties":{"resourceMetrics":{"type":"array","maxItems":2,"items":{"type":"object","properties":{"resource":{"type":"object","properties":{"attributes":{"type":"array","maxItems":4,"items":{"$ref":"#/components/schemas/KeyValue"}}}},"scopeMetrics":{"type":"array","maxItems":2,"items":{"type":"object","properties":{"metrics":{"type":"array","maxItems":3,"items":{"type":"object","properties":{"name":{"type":"string","maxLength":30},"unit":{"type":"string","maxLength":10}}}}}}}}}}}},"ExportResponse":{"type":"object","required":["partialSuccess"],"properties":{"partialSuccess":{"type":"object","properties":{"rejectedSpans":{"type":["string","integer"]},"rejectedLogRecords":{"type":["string","integer"]},"rejectedDataPoints":{"type":["string","integer"]},"errorMessage":{"type":"string"}}}}},"RpcStatus":{"type":"object","required":["code","message"],"properties":{"code":{"type":"integer"},"message":{"type":"string"}}},"O2Error":{"type":"object","required":["code","message"],"properties":{"code":{"type":"integer"},"message":{"type":"string"},"error_detail":{"type":"string"}}},"Organizations":{"type":"object","required":["data"],"properties":{"data":{"type":"array","items":{"type":"object","required":["identifier","name"],"properties":{"id":{"type":"integer"},"identifier":{"type":"string","x-mockingbird-resource":{"type":"organization","identity":true}},"name":{"type":"string"},"type":{"type":"string"}}}}}},"StreamList":{"type":"object","required":["list"],"properties":{"list":{"type":"array","items":{"type":"object","required":["name","stream_type"],"properties":{"name":{"type":"string"},"stream_type":{"type":"string"},"storage_type":{"type":"string"},"stats":{"type":"object"}}}}}},"StreamSchema":{"type":"object","required":["name","stream_type","schema"],"properties":{"name":{"type":"string"},"stream_type":{"type":"string"},"storage_type":{"type":"string"},"stats":{"type":"object"},"schema":{"type":"array","items":{"type":"object","required":["name","type"],"properties":{"name":{"type":"string"},"type":{"type":"string","enum":["Utf8","Int64","Float64","Boolean"]}}}},"settings":{"type":"object"}}},"SearchResponse":{"type":"object","required":["took","hits","total","from","size"],"properties":{"took":{"type":"integer","x-mockingbird-volatile":{"kind":"opaque"}},"hits":{"type":"array","items":{"type":"object"}},"total":{"type":"integer"},"from":{"type":"integer"},"size":{"type":"integer"},"scan_size":{"type":"integer"},"scan_records":{"type":"integer"},"is_partial":{"type":"boolean"},"cached_ratio":{"type":"integer"}}}}}}`);
|
|
3107
|
+
var operationIds = ["ExportTraces", "PreflightTraces", "ExportLogs", "PreflightLogs", "ExportMetrics", "PreflightMetrics", "ListOrganizations", "ListStreams", "GetStreamSchema", "Search"];
|
|
3108
|
+
var supportedOperationIds = ["ExportTraces", "PreflightTraces", "ExportLogs", "PreflightLogs", "ExportMetrics", "PreflightMetrics", "ListOrganizations", "ListStreams", "GetStreamSchema", "Search"];
|
|
3053
3109
|
|
|
3054
3110
|
// src/otlp.ts
|
|
3055
3111
|
var isRecord5 = (value) => typeof value === "object" && value !== null && !Array.isArray(value);
|
|
@@ -4100,13 +4156,17 @@ var execute = (query, rows) => {
|
|
|
4100
4156
|
};
|
|
4101
4157
|
|
|
4102
4158
|
// src/state.ts
|
|
4159
|
+
var INGEST_AUTH_MODES = ["bearer", "basic", "none"];
|
|
4103
4160
|
var DEFAULT_ORGANIZATIONS = [
|
|
4104
4161
|
{ identifier: "default", name: "default" },
|
|
4105
4162
|
{ identifier: "30rBqcDevOrg7Hn2KmQ4xW9sLtY", name: "development" },
|
|
4106
4163
|
{ identifier: "3HSzeProdOrg5Jd8VpN1cR6gTfB", name: "production" }
|
|
4107
4164
|
];
|
|
4108
4165
|
var DEFAULT_SETTINGS = {
|
|
4166
|
+
ingestAuth: "bearer",
|
|
4109
4167
|
ingestTokens: [],
|
|
4168
|
+
ingestUsers: [],
|
|
4169
|
+
cors: { allowedOrigins: [] },
|
|
4110
4170
|
searchUsers: [],
|
|
4111
4171
|
organizations: [...DEFAULT_ORGANIZATIONS],
|
|
4112
4172
|
routing: { byEnvironment: { production: "production" }, default: "development" },
|
|
@@ -4132,8 +4192,9 @@ var OtelState = class {
|
|
|
4132
4192
|
this.settings.insert("settings", { ...DEFAULT_SETTINGS, ...this.seed.settings });
|
|
4133
4193
|
}
|
|
4134
4194
|
}
|
|
4195
|
+
/** Stored settings over the defaults, so a snapshot from before a setting existed still reads. */
|
|
4135
4196
|
current() {
|
|
4136
|
-
return this.settings.get("settings")
|
|
4197
|
+
return { ...DEFAULT_SETTINGS, ...this.settings.get("settings") };
|
|
4137
4198
|
}
|
|
4138
4199
|
update(patch) {
|
|
4139
4200
|
const next = { ...this.current(), ...patch };
|
|
@@ -4197,6 +4258,28 @@ var OtelState = class {
|
|
|
4197
4258
|
}
|
|
4198
4259
|
};
|
|
4199
4260
|
|
|
4261
|
+
// src/status.ts
|
|
4262
|
+
var PROTOBUF = "application/x-protobuf";
|
|
4263
|
+
var mediaType = (request) => request.headers.get("content-type")?.split(";")[0]?.trim().toLowerCase() ?? "";
|
|
4264
|
+
var varint = (value) => {
|
|
4265
|
+
const bytes = [];
|
|
4266
|
+
let rest = value >>> 0;
|
|
4267
|
+
while (rest > 127) {
|
|
4268
|
+
bytes.push(rest & 127 | 128);
|
|
4269
|
+
rest >>>= 7;
|
|
4270
|
+
}
|
|
4271
|
+
bytes.push(rest);
|
|
4272
|
+
return bytes;
|
|
4273
|
+
};
|
|
4274
|
+
var encodeStatus = (code, message) => {
|
|
4275
|
+
const text2 = new TextEncoder().encode(message);
|
|
4276
|
+
return Uint8Array.from([
|
|
4277
|
+
...code === 0 ? [] : [8, ...varint(code)],
|
|
4278
|
+
...text2.length === 0 ? [] : [18, ...varint(text2.length), ...text2]
|
|
4279
|
+
]);
|
|
4280
|
+
};
|
|
4281
|
+
var rpcStatus = (request, status, code, message) => mediaType(request) === PROTOBUF ? new Response(encodeStatus(code, message), { status, headers: { "content-type": PROTOBUF } }) : jsonRes(status, { code, message });
|
|
4282
|
+
|
|
4200
4283
|
// src/runtime.ts
|
|
4201
4284
|
var rpc = (code, message) => ({ code, message });
|
|
4202
4285
|
var OTEL_PRESETS = {
|
|
@@ -4205,6 +4288,7 @@ var OTEL_PRESETS = {
|
|
|
4205
4288
|
rules: [
|
|
4206
4289
|
{
|
|
4207
4290
|
pathPrefix: "/v1/",
|
|
4291
|
+
method: "POST",
|
|
4208
4292
|
status: 429,
|
|
4209
4293
|
headers: { "retry-after": "1" },
|
|
4210
4294
|
body: rpc(8, "rate limited")
|
|
@@ -4213,27 +4297,27 @@ var OTEL_PRESETS = {
|
|
|
4213
4297
|
},
|
|
4214
4298
|
bad_gateway: {
|
|
4215
4299
|
description: "Exports answer 502 (the SDK retries)",
|
|
4216
|
-
rules: [{ pathPrefix: "/v1/", status: 502, body: rpc(14, "bad gateway") }]
|
|
4300
|
+
rules: [{ pathPrefix: "/v1/", method: "POST", status: 502, body: rpc(14, "bad gateway") }]
|
|
4217
4301
|
},
|
|
4218
4302
|
unavailable: {
|
|
4219
4303
|
description: "Exports answer 503 (the SDK retries)",
|
|
4220
|
-
rules: [{ pathPrefix: "/v1/", status: 503, body: rpc(14, "unavailable") }]
|
|
4304
|
+
rules: [{ pathPrefix: "/v1/", method: "POST", status: 503, body: rpc(14, "unavailable") }]
|
|
4221
4305
|
},
|
|
4222
4306
|
gateway_timeout: {
|
|
4223
4307
|
description: "Exports answer 504 (the SDK retries)",
|
|
4224
|
-
rules: [{ pathPrefix: "/v1/", status: 504, body: rpc(4, "deadline exceeded") }]
|
|
4308
|
+
rules: [{ pathPrefix: "/v1/", method: "POST", status: 504, body: rpc(4, "deadline exceeded") }]
|
|
4225
4309
|
},
|
|
4226
4310
|
server_error: {
|
|
4227
4311
|
description: "Exports answer 500 (the SDK drops the batch: not retryable)",
|
|
4228
|
-
rules: [{ pathPrefix: "/v1/", status: 500, body: rpc(13, "internal error") }]
|
|
4312
|
+
rules: [{ pathPrefix: "/v1/", method: "POST", status: 500, body: rpc(13, "internal error") }]
|
|
4229
4313
|
},
|
|
4230
4314
|
unauthorized: {
|
|
4231
|
-
description: "Exports answer 401 as if
|
|
4232
|
-
rules: [{ pathPrefix: "/v1/", status: 401, body: rpc(16, "Unauthenticated") }]
|
|
4315
|
+
description: "Exports answer 401 as if the credentials were wrong (dropped, never retried)",
|
|
4316
|
+
rules: [{ pathPrefix: "/v1/", method: "POST", status: 401, body: rpc(16, "Unauthenticated") }]
|
|
4233
4317
|
},
|
|
4234
4318
|
partial_success: {
|
|
4235
4319
|
description: "Exports answer 200 with partialSuccess rejecting every item (JSON only); nothing is stored",
|
|
4236
|
-
rules: [{ pathPrefix: "/v1/", effect: "partial_success" }]
|
|
4320
|
+
rules: [{ pathPrefix: "/v1/", method: "POST", effect: "partial_success" }]
|
|
4237
4321
|
},
|
|
4238
4322
|
search_unavailable: {
|
|
4239
4323
|
description: "O2 search answers 503 (our clients degrade: empty hops, error result)",
|
|
@@ -4252,6 +4336,24 @@ var matchesWhere = (row, where) => Object.entries(where).every(([key, value]) =>
|
|
|
4252
4336
|
if (formatted in row) return same(row[formatted], value);
|
|
4253
4337
|
return same(row[`service_${formatted}`], value);
|
|
4254
4338
|
});
|
|
4339
|
+
var isStrings = (value) => Array.isArray(value) && value.every((item) => typeof item === "string");
|
|
4340
|
+
var CORS_SHAPE = "cors: {allowedOrigins: string[], allowedHeaders?: string[], allowedMethods?: string[], exposedHeaders?: string[], maxAge?: number}";
|
|
4341
|
+
var corsSettings = (value) => {
|
|
4342
|
+
if (!isRecord6(value) || !isStrings(value.allowedOrigins)) return void 0;
|
|
4343
|
+
const cors = { allowedOrigins: value.allowedOrigins };
|
|
4344
|
+
for (const key of ["allowedHeaders", "allowedMethods", "exposedHeaders"]) {
|
|
4345
|
+
const list2 = value[key];
|
|
4346
|
+
if (list2 === void 0) continue;
|
|
4347
|
+
if (!isStrings(list2)) return void 0;
|
|
4348
|
+
cors[key] = list2;
|
|
4349
|
+
}
|
|
4350
|
+
if (value.maxAge !== void 0) {
|
|
4351
|
+
if (typeof value.maxAge !== "number" || !Number.isInteger(value.maxAge)) return void 0;
|
|
4352
|
+
cors.maxAge = value.maxAge;
|
|
4353
|
+
}
|
|
4354
|
+
return cors;
|
|
4355
|
+
};
|
|
4356
|
+
var users = (value) => Array.isArray(value) && value.every(isRecord6) ? value.map((u) => ({ username: String(u.username), password: String(u.password ?? "") })) : void 0;
|
|
4255
4357
|
var WAIT_POLL_MS = 20;
|
|
4256
4358
|
var MAX_WAIT_MS = 6e4;
|
|
4257
4359
|
var adminRoutes = (runtime) => {
|
|
@@ -4328,18 +4430,30 @@ var adminRoutes = (runtime) => {
|
|
|
4328
4430
|
"PUT /settings": ({ body, namespace }) => {
|
|
4329
4431
|
if (!isRecord6(body)) return adminError4(400, "expected a JSON object");
|
|
4330
4432
|
const patch = {};
|
|
4433
|
+
if (body.ingestAuth !== void 0) {
|
|
4434
|
+
if (!INGEST_AUTH_MODES.includes(body.ingestAuth)) {
|
|
4435
|
+
return adminError4(400, `ingestAuth: ${INGEST_AUTH_MODES.join(" | ")}`);
|
|
4436
|
+
}
|
|
4437
|
+
patch.ingestAuth = body.ingestAuth;
|
|
4438
|
+
}
|
|
4331
4439
|
if (body.ingestTokens !== void 0) {
|
|
4332
4440
|
if (!Array.isArray(body.ingestTokens)) return adminError4(400, "ingestTokens: string[]");
|
|
4333
4441
|
patch.ingestTokens = body.ingestTokens.map(String);
|
|
4334
4442
|
}
|
|
4443
|
+
if (body.ingestUsers !== void 0) {
|
|
4444
|
+
const ingestUsers = users(body.ingestUsers);
|
|
4445
|
+
if (!ingestUsers) return adminError4(400, "ingestUsers: [{username, password}]");
|
|
4446
|
+
patch.ingestUsers = ingestUsers;
|
|
4447
|
+
}
|
|
4448
|
+
if (body.cors !== void 0) {
|
|
4449
|
+
const cors = corsSettings(body.cors);
|
|
4450
|
+
if (!cors) return adminError4(400, CORS_SHAPE);
|
|
4451
|
+
patch.cors = cors;
|
|
4452
|
+
}
|
|
4335
4453
|
if (body.searchUsers !== void 0) {
|
|
4336
|
-
|
|
4337
|
-
|
|
4338
|
-
|
|
4339
|
-
patch.searchUsers = body.searchUsers.map((u) => ({
|
|
4340
|
-
username: String(u.username),
|
|
4341
|
-
password: String(u.password ?? "")
|
|
4342
|
-
}));
|
|
4454
|
+
const searchUsers = users(body.searchUsers);
|
|
4455
|
+
if (!searchUsers) return adminError4(400, "searchUsers: [{username, password}]");
|
|
4456
|
+
patch.searchUsers = searchUsers;
|
|
4343
4457
|
}
|
|
4344
4458
|
if (body.organizations !== void 0) {
|
|
4345
4459
|
if (!Array.isArray(body.organizations) || !body.organizations.every(
|
|
@@ -4395,11 +4509,13 @@ var createRuntime2 = (options = {}) => createRuntime({
|
|
|
4395
4509
|
|
|
4396
4510
|
// src/index.ts
|
|
4397
4511
|
var OTEL_NAMESPACE = "otel";
|
|
4398
|
-
var
|
|
4512
|
+
var RECEIVER_PATHS = /* @__PURE__ */ new Set(["/v1/traces", "/v1/logs", "/v1/metrics"]);
|
|
4399
4513
|
var otelCredential = (request) => bearerToken(request) ?? basicAuth(request)?.username;
|
|
4400
4514
|
var isRecord7 = (value) => typeof value === "object" && value !== null && !Array.isArray(value);
|
|
4401
|
-
var
|
|
4402
|
-
|
|
4515
|
+
var methodNotAllowed = () => new Response("405 method not allowed, supported: [POST]", {
|
|
4516
|
+
status: 405,
|
|
4517
|
+
headers: { "content-type": "text/plain" }
|
|
4518
|
+
});
|
|
4403
4519
|
var unauthorized = () => new Response("Unauthorized Access", {
|
|
4404
4520
|
status: 401,
|
|
4405
4521
|
headers: { "content-type": "text/plain; charset=utf-8" }
|
|
@@ -4420,6 +4536,9 @@ var OtelAPI = class {
|
|
|
4420
4536
|
ExportTraces: (context) => this.export(context, "traces"),
|
|
4421
4537
|
ExportLogs: (context) => this.export(context, "logs"),
|
|
4422
4538
|
ExportMetrics: (context) => this.export(context, "metrics"),
|
|
4539
|
+
PreflightTraces: (context) => this.preflight(context),
|
|
4540
|
+
PreflightLogs: (context) => this.preflight(context),
|
|
4541
|
+
PreflightMetrics: (context) => this.preflight(context),
|
|
4423
4542
|
ListOrganizations: () => this.organizations(),
|
|
4424
4543
|
ListStreams: (context) => this.streams(context),
|
|
4425
4544
|
GetStreamSchema: (context) => this.schema(context),
|
|
@@ -4441,8 +4560,16 @@ var OtelAPI = class {
|
|
|
4441
4560
|
this.app = this.service.app;
|
|
4442
4561
|
this.sqlite = this.service.sqlite;
|
|
4443
4562
|
}
|
|
4444
|
-
/**
|
|
4563
|
+
/** CORS wraps everything the receiver answers, its errors included. */
|
|
4445
4564
|
async fetch(request) {
|
|
4565
|
+
const response = await this.dispatch(request);
|
|
4566
|
+
if (!RECEIVER_PATHS.has(new URL(request.url).pathname) || isPreflight(request)) return response;
|
|
4567
|
+
const cors = this.settings().cors;
|
|
4568
|
+
if (corsEnabled(cors)) applyCors(request, response, cors);
|
|
4569
|
+
return response;
|
|
4570
|
+
}
|
|
4571
|
+
/** Inflate `content-encoding: gzip` bodies (the exporters' `compression: "gzip"`). */
|
|
4572
|
+
async dispatch(request) {
|
|
4446
4573
|
const encoding = request.headers.get("content-encoding")?.toLowerCase();
|
|
4447
4574
|
if (encoding !== "gzip" || request.body === null) return this.service.fetch(request);
|
|
4448
4575
|
let inflated;
|
|
@@ -4451,7 +4578,7 @@ var OtelAPI = class {
|
|
|
4451
4578
|
request.body.pipeThrough(new DecompressionStream("gzip"))
|
|
4452
4579
|
).arrayBuffer();
|
|
4453
4580
|
} catch {
|
|
4454
|
-
return rpcStatus(400, 3, "invalid gzip body");
|
|
4581
|
+
return rpcStatus(request, 400, 3, "invalid gzip body");
|
|
4455
4582
|
}
|
|
4456
4583
|
const headers = new Headers(request.headers);
|
|
4457
4584
|
headers.delete("content-encoding");
|
|
@@ -4477,18 +4604,14 @@ var OtelAPI = class {
|
|
|
4477
4604
|
}
|
|
4478
4605
|
gate(context) {
|
|
4479
4606
|
const operationId = context.operation.operationId;
|
|
4607
|
+
if (operationId.startsWith("Preflight")) return void 0;
|
|
4480
4608
|
if (operationId.startsWith("Export")) {
|
|
4481
|
-
|
|
4482
|
-
const accepted = this.settings().ingestTokens;
|
|
4483
|
-
if (!token || accepted.length > 0 && !accepted.includes(token)) {
|
|
4484
|
-
return rpcStatus(401, 16, "Unauthenticated");
|
|
4485
|
-
}
|
|
4486
|
-
return void 0;
|
|
4609
|
+
return this.ingestAllowed(context.request) ? void 0 : rpcStatus(context.request, 401, 16, "Unauthenticated");
|
|
4487
4610
|
}
|
|
4488
4611
|
const credentials = basicAuth(context.request);
|
|
4489
4612
|
if (!credentials) return unauthorized();
|
|
4490
|
-
const
|
|
4491
|
-
if (
|
|
4613
|
+
const users2 = this.settings().searchUsers;
|
|
4614
|
+
if (users2.length > 0 && !users2.some((u) => u.username === credentials.username && u.password === credentials.password)) {
|
|
4492
4615
|
return unauthorized();
|
|
4493
4616
|
}
|
|
4494
4617
|
const org = context.params.org;
|
|
@@ -4497,6 +4620,26 @@ var OtelAPI = class {
|
|
|
4497
4620
|
}
|
|
4498
4621
|
return void 0;
|
|
4499
4622
|
}
|
|
4623
|
+
/** The receiver's auth mode: nothing, Basic credentials, or (the default) a bearer token. */
|
|
4624
|
+
ingestAllowed(request) {
|
|
4625
|
+
const settings = this.settings();
|
|
4626
|
+
if (settings.ingestAuth === "none") return true;
|
|
4627
|
+
if (settings.ingestAuth === "basic") {
|
|
4628
|
+
const credentials = basicAuth(request);
|
|
4629
|
+
const users2 = settings.ingestUsers;
|
|
4630
|
+
return credentials !== void 0 && (users2.length === 0 || users2.some(
|
|
4631
|
+
(u) => u.username === credentials.username && u.password === credentials.password
|
|
4632
|
+
));
|
|
4633
|
+
}
|
|
4634
|
+
const token = bearerToken(request);
|
|
4635
|
+
const accepted = settings.ingestTokens;
|
|
4636
|
+
return token !== void 0 && (accepted.length === 0 || accepted.includes(token));
|
|
4637
|
+
}
|
|
4638
|
+
/** `OPTIONS` on a receiver route: a CORS preflight when CORS is on, else not a method it takes. */
|
|
4639
|
+
preflight(context) {
|
|
4640
|
+
const cors = this.settings().cors;
|
|
4641
|
+
return corsEnabled(cors) && isPreflight(context.request) ? preflightResponse(context.request, cors) : methodNotAllowed();
|
|
4642
|
+
}
|
|
4500
4643
|
decode(context, kind) {
|
|
4501
4644
|
const type = mediaType(context.request);
|
|
4502
4645
|
const body = context.body;
|
|
@@ -4506,16 +4649,16 @@ var OtelAPI = class {
|
|
|
4506
4649
|
const payload = kind === "traces" ? decodeTraceRequest(bytes) : kind === "logs" ? decodeLogsRequest(bytes) : { resourceMetrics: new Array(countMetricsRequest(bytes)).fill({}) };
|
|
4507
4650
|
return { payload, protobuf: true, bytes: bytes.length };
|
|
4508
4651
|
} catch (error) {
|
|
4509
|
-
if (error instanceof ProtobufError) return rpcStatus(400, 3, error.message);
|
|
4652
|
+
if (error instanceof ProtobufError) return rpcStatus(context.request, 400, 3, error.message);
|
|
4510
4653
|
throw error;
|
|
4511
4654
|
}
|
|
4512
4655
|
}
|
|
4513
4656
|
if (type !== "application/json") {
|
|
4514
|
-
return rpcStatus(415, 3, `unsupported content type ${type || "(none)"}`);
|
|
4657
|
+
return rpcStatus(context.request, 415, 3, `unsupported content type ${type || "(none)"}`);
|
|
4515
4658
|
}
|
|
4516
4659
|
if (body.kind === "empty") return { payload: {}, protobuf: false, bytes: 0 };
|
|
4517
4660
|
if (body.kind !== "json" || !isRecord7(body.value)) {
|
|
4518
|
-
return rpcStatus(400, 3, "request body is not an OTLP/JSON export request");
|
|
4661
|
+
return rpcStatus(context.request, 400, 3, "request body is not an OTLP/JSON export request");
|
|
4519
4662
|
}
|
|
4520
4663
|
return { payload: body.value, protobuf: false, bytes: JSON.stringify(body.value).length };
|
|
4521
4664
|
}
|
|
@@ -4688,6 +4831,7 @@ export {
|
|
|
4688
4831
|
parseSql,
|
|
4689
4832
|
referencedColumns,
|
|
4690
4833
|
execute,
|
|
4834
|
+
INGEST_AUTH_MODES,
|
|
4691
4835
|
DEFAULT_ORGANIZATIONS,
|
|
4692
4836
|
DEFAULT_SETTINGS,
|
|
4693
4837
|
OTEL_PRESETS,
|
|
@@ -4697,4 +4841,4 @@ export {
|
|
|
4697
4841
|
OtelAPI,
|
|
4698
4842
|
adminRow
|
|
4699
4843
|
};
|
|
4700
|
-
//# sourceMappingURL=chunk-
|
|
4844
|
+
//# sourceMappingURL=chunk-T4AU5UCQ.js.map
|