# Copyright The OpenTelemetry Authors
# SPDX-License-Identifier: Apache-2.0


from typing import Final

from opentelemetry.metrics import Counter, Histogram, Meter, UpDownCounter

OTEL_SDK_EXPORTER_LOG_EXPORTED: Final = "otel.sdk.exporter.log.exported"
"""
The number of log records for which the export has finished, either successful or failed
Instrument: counter
Unit: {log_record}
Note: For successful exports, `error.type` MUST NOT be set. For failed exports, `error.type` MUST contain the failure cause.
For exporters with partial success semantics (e.g. OTLP with `rejected_log_records`), rejected log records MUST count as failed and only non-rejected log records count as success.
If no rejection reason is available, `rejected` SHOULD be used as value for `error.type`.
If the exporter retries failed export attempts, the export operation is considered finished only after the final attempt has concluded.
Each log record MUST be counted exactly once per export operation: intermediate failed attempts that are followed by a retry MUST NOT increment the counter,
and `error.type` reflects the cause of the final attempt.
"""


def create_otel_sdk_exporter_log_exported(meter: Meter) -> Counter:
    """The number of log records for which the export has finished, either successful or failed"""
    return meter.create_counter(
        name=OTEL_SDK_EXPORTER_LOG_EXPORTED,
        description="The number of log records for which the export has finished, either successful or failed.",
        unit="{log_record}",
    )


OTEL_SDK_EXPORTER_LOG_INFLIGHT: Final = "otel.sdk.exporter.log.inflight"
"""
The number of log records which were passed to the exporter, but that have not been exported yet (neither successful, nor failed)
Instrument: updowncounter
Unit: {log_record}
Note: Log records are counted as inflight from when they are passed to the exporter until the export operation has concluded.
If the exporter retries failed export attempts, log records remain inflight across all retry attempts and any backoff between them.
"""


def create_otel_sdk_exporter_log_inflight(meter: Meter) -> UpDownCounter:
    """The number of log records which were passed to the exporter, but that have not been exported yet (neither successful, nor failed)"""
    return meter.create_up_down_counter(
        name=OTEL_SDK_EXPORTER_LOG_INFLIGHT,
        description="The number of log records which were passed to the exporter, but that have not been exported yet (neither successful, nor failed).",
        unit="{log_record}",
    )


OTEL_SDK_EXPORTER_METRIC_DATA_POINT_EXPORTED: Final = "otel.sdk.exporter.metric_data_point.exported"
"""
The number of metric data points for which the export has finished, either successful or failed
Instrument: counter
Unit: {data_point}
Note: For successful exports, `error.type` MUST NOT be set. For failed exports, `error.type` MUST contain the failure cause.
For exporters with partial success semantics (e.g. OTLP with `rejected_data_points`), rejected data points MUST count as failed and only non-rejected data points count as success.
If no rejection reason is available, `rejected` SHOULD be used as value for `error.type`.
If the exporter retries failed export attempts, the export operation is considered finished only after the final attempt has concluded.
Each metric data point MUST be counted exactly once per export operation: intermediate failed attempts that are followed by a retry MUST NOT increment the counter,
and `error.type` reflects the cause of the final attempt.
"""


def create_otel_sdk_exporter_metric_data_point_exported(meter: Meter) -> Counter:
    """The number of metric data points for which the export has finished, either successful or failed"""
    return meter.create_counter(
        name=OTEL_SDK_EXPORTER_METRIC_DATA_POINT_EXPORTED,
        description="The number of metric data points for which the export has finished, either successful or failed.",
        unit="{data_point}",
    )


OTEL_SDK_EXPORTER_METRIC_DATA_POINT_INFLIGHT: Final = "otel.sdk.exporter.metric_data_point.inflight"
"""
The number of metric data points which were passed to the exporter, but that have not been exported yet (neither successful, nor failed)
Instrument: updowncounter
Unit: {data_point}
Note: Metric data points are counted as inflight from when they are passed to the exporter until the export operation has concluded.
If the exporter retries failed export attempts, metric data points remain inflight across all retry attempts and any backoff between them.
"""


def create_otel_sdk_exporter_metric_data_point_inflight(meter: Meter) -> UpDownCounter:
    """The number of metric data points which were passed to the exporter, but that have not been exported yet (neither successful, nor failed)"""
    return meter.create_up_down_counter(
        name=OTEL_SDK_EXPORTER_METRIC_DATA_POINT_INFLIGHT,
        description="The number of metric data points which were passed to the exporter, but that have not been exported yet (neither successful, nor failed).",
        unit="{data_point}",
    )


OTEL_SDK_EXPORTER_OPERATION_DURATION: Final = "otel.sdk.exporter.operation.duration"
"""
The duration of exporting a batch of telemetry records
Instrument: histogram
Unit: s
Note: This metric defines successful operations using the full success definitions for [HTTP](https://github.com/open-telemetry/opentelemetry-proto/blob/v1.5.0/docs/specification.md#full-success-1)
and [gRPC](https://github.com/open-telemetry/opentelemetry-proto/blob/v1.5.0/docs/specification.md#full-success). Anything else is defined as an unsuccessful operation. For successful
operations, `error.type` MUST NOT be set. For unsuccessful export operations, `error.type` MUST contain a relevant failure cause.
If the exporter retries failed export attempts, exactly one observation MUST be recorded per export operation,
covering the wall-clock duration from the start of the first attempt through the conclusion of the final attempt (including any backoff between attempts).
`error.type` reflects the cause of the final attempt.
"""


def create_otel_sdk_exporter_operation_duration(meter: Meter) -> Histogram:
    """The duration of exporting a batch of telemetry records"""
    return meter.create_histogram(
        name=OTEL_SDK_EXPORTER_OPERATION_DURATION,
        description="The duration of exporting a batch of telemetry records.",
        unit="s",
    )


OTEL_SDK_EXPORTER_SPAN_EXPORTED: Final = "otel.sdk.exporter.span.exported"
"""
The number of spans for which the export has finished, either successful or failed
Instrument: counter
Unit: {span}
Note: For successful exports, `error.type` MUST NOT be set. For failed exports, `error.type` MUST contain the failure cause.
For exporters with partial success semantics (e.g. OTLP with `rejected_spans`), rejected spans MUST count as failed and only non-rejected spans count as success.
If no rejection reason is available, `rejected` SHOULD be used as value for `error.type`.
If the exporter retries failed export attempts, the export operation is considered finished only after the final attempt has concluded.
Each span MUST be counted exactly once per export operation: intermediate failed attempts that are followed by a retry MUST NOT increment the counter,
and `error.type` reflects the cause of the final attempt.
"""


def create_otel_sdk_exporter_span_exported(meter: Meter) -> Counter:
    """The number of spans for which the export has finished, either successful or failed"""
    return meter.create_counter(
        name=OTEL_SDK_EXPORTER_SPAN_EXPORTED,
        description="The number of spans for which the export has finished, either successful or failed.",
        unit="{span}",
    )


OTEL_SDK_EXPORTER_SPAN_EXPORTED_COUNT: Final = "otel.sdk.exporter.span.exported.count"
"""
Deprecated: Replaced by `otel.sdk.exporter.span.exported`.
"""


def create_otel_sdk_exporter_span_exported_count(meter: Meter) -> UpDownCounter:
    """Deprecated, use `otel.sdk.exporter.span.exported` instead"""
    return meter.create_up_down_counter(
        name=OTEL_SDK_EXPORTER_SPAN_EXPORTED_COUNT,
        description="Deprecated, use `otel.sdk.exporter.span.exported` instead.",
        unit="{span}",
    )


OTEL_SDK_EXPORTER_SPAN_INFLIGHT: Final = "otel.sdk.exporter.span.inflight"
"""
The number of spans which were passed to the exporter, but that have not been exported yet (neither successful, nor failed)
Instrument: updowncounter
Unit: {span}
Note: Spans are counted as inflight from when they are passed to the exporter until the export operation has concluded.
If the exporter retries failed export attempts, spans remain inflight across all retry attempts and any backoff between them.
"""


def create_otel_sdk_exporter_span_inflight(meter: Meter) -> UpDownCounter:
    """The number of spans which were passed to the exporter, but that have not been exported yet (neither successful, nor failed)"""
    return meter.create_up_down_counter(
        name=OTEL_SDK_EXPORTER_SPAN_INFLIGHT,
        description="The number of spans which were passed to the exporter, but that have not been exported yet (neither successful, nor failed).",
        unit="{span}",
    )


OTEL_SDK_EXPORTER_SPAN_INFLIGHT_COUNT: Final = "otel.sdk.exporter.span.inflight.count"
"""
Deprecated: Replaced by `otel.sdk.exporter.span.inflight`.
"""


def create_otel_sdk_exporter_span_inflight_count(meter: Meter) -> UpDownCounter:
    """Deprecated, use `otel.sdk.exporter.span.inflight` instead"""
    return meter.create_up_down_counter(
        name=OTEL_SDK_EXPORTER_SPAN_INFLIGHT_COUNT,
        description="Deprecated, use `otel.sdk.exporter.span.inflight` instead.",
        unit="{span}",
    )


OTEL_SDK_LOG_CREATED: Final = "otel.sdk.log.created"
"""
The number of logs submitted to enabled SDK Loggers
Instrument: counter
Unit: {log_record}
"""


def create_otel_sdk_log_created(meter: Meter) -> Counter:
    """The number of logs submitted to enabled SDK Loggers"""
    return meter.create_counter(
        name=OTEL_SDK_LOG_CREATED,
        description="The number of logs submitted to enabled SDK Loggers.",
        unit="{log_record}",
    )


OTEL_SDK_METRIC_READER_COLLECTION_DURATION: Final = "otel.sdk.metric_reader.collection.duration"
"""
The duration of the collect operation of the metric reader
Instrument: histogram
Unit: s
Note: For successful collections, `error.type` MUST NOT be set. For failed collections, `error.type` SHOULD contain the failure cause.
It can happen that metrics collection is successful for some MetricProducers, while others fail. In that case `error.type` SHOULD be set to any of the failure causes.
"""


def create_otel_sdk_metric_reader_collection_duration(meter: Meter) -> Histogram:
    """The duration of the collect operation of the metric reader"""
    return meter.create_histogram(
        name=OTEL_SDK_METRIC_READER_COLLECTION_DURATION,
        description="The duration of the collect operation of the metric reader.",
        unit="s",
    )


OTEL_SDK_PROCESSOR_LOG_PROCESSED: Final = "otel.sdk.processor.log.processed"
"""
The number of log records for which the processing has finished, either successful or failed
Instrument: counter
Unit: {log_record}
Note: For successful processing, `error.type` MUST NOT be set. For failed processing, `error.type` MUST contain the failure cause.
SDK Batching Log Record Processors MUST use `queue_full` as the value of `error.type` for log records dropped due to a full queue.
If a processor reports a log record dropped because it has already been shut down, `error.type` MUST be `already_shutdown`.
Whether and when a processor drops such log records is governed by the SDK specification, not by this metric.
For the SDK Simple and Batching Log Record Processors, a log record MUST be counted as successfully processed at the point the
processor invokes the export operation. For batching processors, all log records in the batch passed to the exporter are counted
at that point; log records accepted into the processor's queue but not yet passed to the exporter have not been processed.
Implementations MUST NOT delay this count until the export operation concludes, and the outcome of the export operation,
including an immediate failure of the invocation itself, MUST NOT affect this metric.
Export outcomes are reported by `otel.sdk.exporter.log.exported`.
"""


def create_otel_sdk_processor_log_processed(meter: Meter) -> Counter:
    """The number of log records for which the processing has finished, either successful or failed"""
    return meter.create_counter(
        name=OTEL_SDK_PROCESSOR_LOG_PROCESSED,
        description="The number of log records for which the processing has finished, either successful or failed.",
        unit="{log_record}",
    )


OTEL_SDK_PROCESSOR_LOG_QUEUE_CAPACITY: Final = "otel.sdk.processor.log.queue.capacity"
"""
The maximum number of log records the queue of a given instance of an SDK Log Record processor can hold
Instrument: updowncounter
Unit: {log_record}
Note: Only applies to Log Record processors which use a queue, e.g. the SDK Batching Log Record Processor.
"""


def create_otel_sdk_processor_log_queue_capacity(meter: Meter) -> UpDownCounter:
    """The maximum number of log records the queue of a given instance of an SDK Log Record processor can hold"""
    return meter.create_up_down_counter(
        name=OTEL_SDK_PROCESSOR_LOG_QUEUE_CAPACITY,
        description="The maximum number of log records the queue of a given instance of an SDK Log Record processor can hold.",
        unit="{log_record}",
    )


OTEL_SDK_PROCESSOR_LOG_QUEUE_SIZE: Final = "otel.sdk.processor.log.queue.size"
"""
The number of log records in the queue of a given instance of an SDK log processor
Instrument: updowncounter
Unit: {log_record}
Note: Only applies to log record processors which use a queue, e.g. the SDK Batching Log Record Processor.
"""


def create_otel_sdk_processor_log_queue_size(meter: Meter) -> UpDownCounter:
    """The number of log records in the queue of a given instance of an SDK log processor"""
    return meter.create_up_down_counter(
        name=OTEL_SDK_PROCESSOR_LOG_QUEUE_SIZE,
        description="The number of log records in the queue of a given instance of an SDK log processor.",
        unit="{log_record}",
    )


OTEL_SDK_PROCESSOR_SPAN_PROCESSED: Final = "otel.sdk.processor.span.processed"
"""
The number of spans for which the processing has finished, either successful or failed
Instrument: counter
Unit: {span}
Note: For successful processing, `error.type` MUST NOT be set. For failed processing, `error.type` MUST contain the failure cause.
SDK Batching Span Processors MUST use `queue_full` as the value of `error.type` for spans dropped due to a full queue.
If a processor reports a span dropped because it has already been shut down, `error.type` MUST be `already_shutdown`.
Whether and when a processor drops such spans is governed by the SDK specification, not by this metric.
For the SDK Simple and Batching Span Processors, a span MUST be counted as successfully processed at the point the processor
invokes the export operation. For batching processors, all spans in the batch passed to the exporter are counted at that point;
spans accepted into the processor's queue but not yet passed to the exporter have not been processed.
Implementations MUST NOT delay this count until the export operation concludes, and the outcome of the export operation,
including an immediate failure of the invocation itself, MUST NOT affect this metric.
Export outcomes are reported by `otel.sdk.exporter.span.exported`.
"""


def create_otel_sdk_processor_span_processed(meter: Meter) -> Counter:
    """The number of spans for which the processing has finished, either successful or failed"""
    return meter.create_counter(
        name=OTEL_SDK_PROCESSOR_SPAN_PROCESSED,
        description="The number of spans for which the processing has finished, either successful or failed.",
        unit="{span}",
    )


OTEL_SDK_PROCESSOR_SPAN_PROCESSED_COUNT: Final = "otel.sdk.processor.span.processed.count"
"""
Deprecated: Replaced by `otel.sdk.processor.span.processed`.
"""


def create_otel_sdk_processor_span_processed_count(meter: Meter) -> UpDownCounter:
    """Deprecated, use `otel.sdk.processor.span.processed` instead"""
    return meter.create_up_down_counter(
        name=OTEL_SDK_PROCESSOR_SPAN_PROCESSED_COUNT,
        description="Deprecated, use `otel.sdk.processor.span.processed` instead.",
        unit="{span}",
    )


OTEL_SDK_PROCESSOR_SPAN_QUEUE_CAPACITY: Final = "otel.sdk.processor.span.queue.capacity"
"""
The maximum number of spans the queue of a given instance of an SDK span processor can hold
Instrument: updowncounter
Unit: {span}
Note: Only applies to span processors which use a queue, e.g. the SDK Batching Span Processor.
"""


def create_otel_sdk_processor_span_queue_capacity(meter: Meter) -> UpDownCounter:
    """The maximum number of spans the queue of a given instance of an SDK span processor can hold"""
    return meter.create_up_down_counter(
        name=OTEL_SDK_PROCESSOR_SPAN_QUEUE_CAPACITY,
        description="The maximum number of spans the queue of a given instance of an SDK span processor can hold.",
        unit="{span}",
    )


OTEL_SDK_PROCESSOR_SPAN_QUEUE_SIZE: Final = "otel.sdk.processor.span.queue.size"
"""
The number of spans in the queue of a given instance of an SDK span processor
Instrument: updowncounter
Unit: {span}
Note: Only applies to span processors which use a queue, e.g. the SDK Batching Span Processor.
"""


def create_otel_sdk_processor_span_queue_size(meter: Meter) -> UpDownCounter:
    """The number of spans in the queue of a given instance of an SDK span processor"""
    return meter.create_up_down_counter(
        name=OTEL_SDK_PROCESSOR_SPAN_QUEUE_SIZE,
        description="The number of spans in the queue of a given instance of an SDK span processor.",
        unit="{span}",
    )


OTEL_SDK_SPAN_ENDED: Final = "otel.sdk.span.ended"
"""
Deprecated: Obsoleted.
"""


def create_otel_sdk_span_ended(meter: Meter) -> Counter:
    """Use `otel.sdk.span.started` minus `otel.sdk.span.live` to derive this value"""
    return meter.create_counter(
        name=OTEL_SDK_SPAN_ENDED,
        description="Use `otel.sdk.span.started` minus `otel.sdk.span.live` to derive this value.",
        unit="{span}",
    )


OTEL_SDK_SPAN_ENDED_COUNT: Final = "otel.sdk.span.ended.count"
"""
Deprecated: Obsoleted.
"""


def create_otel_sdk_span_ended_count(meter: Meter) -> Counter:
    """Use `otel.sdk.span.started` minus `otel.sdk.span.live` to derive this value"""
    return meter.create_counter(
        name=OTEL_SDK_SPAN_ENDED_COUNT,
        description="Use `otel.sdk.span.started` minus `otel.sdk.span.live` to derive this value.",
        unit="{span}",
    )


OTEL_SDK_SPAN_LIVE: Final = "otel.sdk.span.live"
"""
The number of created spans with `recording=true` for which the end operation has not been called yet
Instrument: updowncounter
Unit: {span}
Note: Non-recording spans are not counted, hence `otel.span.sampling_result` can only take values `RECORD_ONLY` and `RECORD_AND_SAMPLE`, not `DROP`.
"""


def create_otel_sdk_span_live(meter: Meter) -> UpDownCounter:
    """The number of created spans with `recording=true` for which the end operation has not been called yet"""
    return meter.create_up_down_counter(
        name=OTEL_SDK_SPAN_LIVE,
        description="The number of created spans with `recording=true` for which the end operation has not been called yet.",
        unit="{span}",
    )


OTEL_SDK_SPAN_LIVE_COUNT: Final = "otel.sdk.span.live.count"
"""
Deprecated: Replaced by `otel.sdk.span.live`.
"""


def create_otel_sdk_span_live_count(meter: Meter) -> UpDownCounter:
    """Deprecated, use `otel.sdk.span.live` instead"""
    return meter.create_up_down_counter(
        name=OTEL_SDK_SPAN_LIVE_COUNT,
        description="Deprecated, use `otel.sdk.span.live` instead.",
        unit="{span}",
    )


OTEL_SDK_SPAN_STARTED: Final = "otel.sdk.span.started"
"""
The number of created spans
Instrument: counter
Unit: {span}
Note: Implementations MUST record this metric for all spans, even for non-recording ones.
"""


def create_otel_sdk_span_started(meter: Meter) -> Counter:
    """The number of created spans"""
    return meter.create_counter(
        name=OTEL_SDK_SPAN_STARTED,
        description="The number of created spans.",
        unit="{span}",
    )
