# TelemetryDestination

Source: /reference/telemetrydestinations/

Where the fleet's telemetry goes. Modelplane composes no collectors until a TelemetryDestination exists: neither tier stores anything, so collecting with nowhere to export would spend GPU-cluster memory on samples nobody reads. Creating one turns collection on everywhere at once.
There is no per-deployment opt-out. A ModelDeployment's author owns neither the destination nor its bill.

Apply instances as `apiVersion: modelplane.ai/v1alpha1`, `kind: TelemetryDestination`.

[Concept guide: Monitor the Fleet](/platform/telemetry/index.md)

## Definition

The CompositeResourceDefinition this reference is generated from, with the complete OpenAPI schema, validation rules, and defaults:

```yaml
apiVersion: apiextensions.crossplane.io/v2
kind: CompositeResourceDefinition
metadata:
  name: telemetrydestinations.modelplane.ai
spec:
  group: modelplane.ai
  names:
    categories: [crossplane, modelplane, platform]
    kind: TelemetryDestination
    plural: telemetrydestinations
    shortNames: [td]
  scope: Cluster
  versions:
  - name: v1alpha1
    served: true
    referenceable: true
    additionalPrinterColumns:
    - name: AGE
      type: date
      jsonPath: .metadata.creationTimestamp
    schema:
      openAPIV3Schema:
        type: object
        required: [spec]
        properties:
          spec:
            type: object
            required: [sinks]
            description: >-
              Where the fleet's telemetry goes. Modelplane composes no
              collectors until a TelemetryDestination exists: neither tier
              stores anything, so collecting with nowhere to export would
              spend GPU-cluster memory on samples nobody reads. Creating one
              turns collection on everywhere at once.

              There is no per-deployment opt-out. A ModelDeployment's author
              owns neither the destination nor its bill.
            properties:
              sinks:
                type: array
                minItems: 1
                maxItems: 16
                description: >-
                  Where to send it. Every sink gets the whole stream, so two
                  sinks is two copies of the fleet's metrics, billed twice.
                x-kubernetes-list-type: map
                x-kubernetes-list-map-keys: [name]
                items:
                  type: object
                  required: [name, type]
                  x-kubernetes-validations:
                  - rule: "!has(self.auth) || has(self.secretRef)"
                    message: secretRef is required when auth is set, because the credential lives in it.
                  properties:
                    name:
                      type: string
                      maxLength: 63
                      pattern: '^[a-z0-9]([-a-z0-9]*[a-z0-9])?$'
                      description: >-
                        This sink's name, unique within the destination. It
                        names the collector's exporter instance, the
                        authenticator Modelplane composes for it, and the
                        directory its credential mounts at, so renaming one
                        restarts the collector.
                    type:
                      type: string
                      maxLength: 63
                      description: >-
                        The collector exporter to send with, by the name
                        OpenTelemetry gives it: otlphttp, otlp,
                        prometheusremotewrite, kafka, and every other one the
                        collector provides.

                        Not an enum, because enumerating them here would mean
                        a Modelplane release for each exporter the collector
                        gains, and the collector already refuses to start on a
                        name it doesn't have.
                    endpoint:
                      type: string
                      maxLength: 2048
                      description: >-
                        Where this sink writes. Typed rather than left to the
                        configuration below because it is the setting every
                        destination has to get right, and the one worth
                        catching here rather than in a collector that won't
                        start.

                        Optional, because not every exporter addresses its
                        destination this way: Kafka takes brokers, the file
                        exporter a path, and the debug exporter nothing at
                        all. Those go in the configuration below, under the
                        names that exporter gives them.
                    auth:
                      type: object
                      description: >-
                        How to authenticate, for the schemes Modelplane
                        composes. The collector takes no credential inline: it
                        authenticates through an extension an exporter names,
                        so setting this composes that extension and wires the
                        reference.

                        A scheme that isn't here is still reachable. Define
                        the extension yourself under spec.extensions and name
                        it from this sink's config, which is what Modelplane
                        does on your behalf.
                      properties:
                        bearerTokenKey:
                          type: string
                          maxLength: 253
                          description: >-
                            The key in this sink's Secret holding the bearer
                            token. Modelplane mounts it as a file and points
                            the authenticator at it, so a rotated token is
                            picked up without restarting the collector.
                    config:
                      type: object
                      x-kubernetes-preserve-unknown-fields: true
                      description: >-
                        Anything else that exporter takes, passed through
                        unread: TLS, retry, queueing, compression, headers.

                        Modelplane does not model an exporter's configuration,
                        because the schema is OpenTelemetry's and versioned
                        separately. Typing it would mean a Modelplane release
                        for each setting the collector gains, and would drop
                        the ones this has never heard of. What is typed above
                        is what belongs to Modelplane: which sinks exist, what
                        each is called, where it writes, and which Secret it
                        reads.
                    secretRef:
                      type: object
                      required: [name]
                      description: >-
                        A Secret holding this sink's credential. Its keys
                        reach the collector as files under
                        /etc/modelplane/telemetry/<sink name>/, and as
                        environment variables, for configuration above
                        referring to ${env:TOKEN}.

                        Per sink rather than per destination, so two sinks
                        with different credentials don't have to share one
                        Secret and tell their keys apart by prefix. The files
                        are per sink; the environment variables are not, so
                        two Secrets sharing a key name still collide there and
                        the file is the one to read.
                      properties:
                        name:
                          type: string
                          maxLength: 253
                          description: Name of the Secret, in Modelplane's namespace.
              extensions:
                type: object
                x-kubernetes-preserve-unknown-fields: true
                description: >-
                  The collector's extensions block, passed through unread,
                  for the authenticator a sink references. Bearer token,
                  basic auth, OIDC and SigV4 all work, because none of them
                  is modelled here.
          status:
            type: object
            properties:
              conditions:
                type: array
                items:
                  type: object
```
