/***
 * Copyright 2026 HAProxy Technologies, Miroslav Zagorac <mzagorac@haproxy.com>
 *
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 *     http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */
#ifndef OPENTELEMETRY_C_WRAPPER_TRACER_H
#define OPENTELEMETRY_C_WRAPPER_TRACER_H

__CPLUSPLUS_DECL_BEGIN

#define OTELC_DBG_TRACER(l,h,p)                                         \
	OTELC_DBG_STRUCT(_##l, h, h " %p:{ %p:\"%s\" %p:\"%s\" }", (p), \
	                 (p)->err, OTELC_STR_ARG((p)->err), (p)->scope_name, OTELC_STR_ARG((p)->scope_name))

/***
 * The tracer operations vtable.
 */
struct otelc_tracer;
struct otelc_tracer_ops {
	/***
	 * NAME
	 *   start_span - starts a new span
	 *
	 * SYNOPSIS
	 *   struct otelc_span *(*start_span)(struct otelc_tracer *tracer, const char *operation_name)
	 *
	 * ARGUMENTS
	 *   tracer         - tracer instance
	 *   operation_name - span name
	 *
	 * DESCRIPTION
	 *   Starts a new span (which represents a unit of work or operation).
	 *   This function calls the function start_span_with_options(), which
	 *   offers additional control over span creation.
	 *
	 * RETURN VALUE
	 *   Returns a pointer to the otelc_span structure used to manage the
	 *   span, or nullptr in case of an error.
	 */
	struct otelc_span *(*start_span)(struct otelc_tracer *tracer, const char *operation_name)
		OTELC_NONNULL_ALL;

	/***
	 * NAME
	 *   start_span_with_options - starts a new span with detailed options
	 *
	 * SYNOPSIS
	 *   struct otelc_span *(*start_span_with_options)(struct otelc_tracer *tracer, const char *operation_name, const struct otelc_span *parent_span, const struct otelc_span_context *parent_context, const struct timespec *ts_steady, const struct timespec *ts_system, otelc_span_kind_t kind, const struct otelc_span_link *links, size_t links_len)
	 *
	 * ARGUMENTS
	 *   tracer         - tracer instance
	 *   operation_name - span name
	 *   parent_span    - parent span for the span being started
	 *   parent_context - parent span context for the span being started
	 *   ts_steady      - a timepoint relative to the monotonic clock epoch
	 *   ts_system      - a timepoint relative to the system clock epoch
	 *   kind           - span type, can be used to further specify the relationship between the spans
	 *   links          - an array of span links to establish at creation time
	 *   links_len      - number of elements in the links array
	 *
	 * DESCRIPTION
	 *   Starts a new span with the specified options, including its name,
	 *   parent (either a span or a context), timestamps, kind and an array
	 *   of span links established at creation time.  This allows for
	 *   fine-grained control over span creation, which is essential for
	 *   accurate distributed tracing.
	 *
	 *   Unlike AddLink (which requires ABI version 2), links at creation
	 *   time are supported by all ABI versions.  Each link references
	 *   either a span or a span context and may carry its own set of
	 *   attributes.  When links is NULL or links_len is 0, it is not used.
	 *
	 *   NOTE: otelc_span_kind_t is an autogenerated enum from the
	 *   OpenTelemetry C++ headers, defined in
	 *   include/opentelemetry-c-wrapper/otel_cpp.h.
	 *
	 * RETURN VALUE
	 *   Returns a pointer to the otelc_span structure used to manage the
	 *   span, or nullptr in case of an error.
	 */
	struct otelc_span *(*start_span_with_options)(struct otelc_tracer *tracer, const char *operation_name, const struct otelc_span *parent_span, const struct otelc_span_context *parent_context, const struct timespec *ts_steady, const struct timespec *ts_system, otelc_span_kind_t kind, const struct otelc_span_link *links, size_t links_len)
		OTELC_NONNULL(1, 2);

	/***
	 * NAME
	 *   extract_text_map - extracts a span context from a text map carrier
	 *
	 * SYNOPSIS
	 *   struct otelc_span_context *(*extract_text_map)(struct otelc_tracer *tracer, const struct otelc_text_map_reader *carrier)
	 *
	 * ARGUMENTS
	 *   tracer  - tracer instance
	 *   carrier - the text map carrier from which to extract the context
	 *
	 * DESCRIPTION
	 *   Extracts a span context from the given text map carrier, allowing
	 *   for the propagation of trace context across process boundaries.
	 *   This is a key mechanism for distributed tracing.
	 *
	 * RETURN VALUE
	 *   Returns a pointer to the extracted span context on success,
	 *   or nullptr on failure.
	 */
	struct otelc_span_context *(*extract_text_map)(struct otelc_tracer *tracer, const struct otelc_text_map_reader *carrier)
		OTELC_NONNULL_ALL;

	/***
	 * NAME
	 *   extract_http_headers - extracts a span context from HTTP headers
	 *
	 * SYNOPSIS
	 *   struct otelc_span_context *(*extract_http_headers)(struct otelc_tracer *tracer, const struct otelc_http_headers_reader *carrier)
	 *
	 * ARGUMENTS
	 *   tracer  - tracer instance
	 *   carrier - the HTTP headers carrier from which to extract the context
	 *
	 * DESCRIPTION
	 *   Extracts a span context from the given HTTP headers carrier,
	 *   which is a common method for propagating trace context in web
	 *   applications.
	 *
	 * RETURN VALUE
	 *   Returns a pointer to the extracted span context on success,
	 *   or nullptr on failure.
	 */
	struct otelc_span_context *(*extract_http_headers)(struct otelc_tracer *tracer, const struct otelc_http_headers_reader *carrier)
		OTELC_NONNULL_ALL;

	/***
	 * NAME
	 *   enabled - checks whether the tracer is enabled
	 *
	 * SYNOPSIS
	 *   int (*enabled)(struct otelc_tracer *tracer)
	 *
	 * ARGUMENTS
	 *   tracer - tracer instance
	 *
	 * DESCRIPTION
	 *   Queries the underlying tracer to determine whether it is enabled.
	 *   Callers can use this check to skip expensive span setup when the
	 *   tracer would discard the data anyway.
	 *
	 * RETURN VALUE
	 *   Returns true if the tracer is enabled, false if it is not,
	 *   or OTELC_RET_ERROR in case of an error.
	 */
	int (*enabled)(struct otelc_tracer *tracer)
		OTELC_NONNULL_ALL;

	/***
	 * NAME
	 *   force_flush - forces the export of any buffered spans
	 *
	 * SYNOPSIS
	 *   int (*force_flush)(struct otelc_tracer *tracer, const struct timespec *timeout)
	 *
	 * ARGUMENTS
	 *   tracer  - tracer instance
	 *   timeout - maximum time to wait, or NULL for no limit
	 *
	 * DESCRIPTION
	 *   Forces the tracer to export all spans that have been collected but
	 *   not yet exported.  This is a blocking call that will not return
	 *   until the export is complete.  The optional timeout argument limits
	 *   how long the operation may block.
	 *
	 * RETURN VALUE
	 *   Returns OTELC_RET_OK on success, or OTELC_RET_ERROR on failure.
	 */
	int (*force_flush)(struct otelc_tracer *tracer, const struct timespec *timeout)
		OTELC_NONNULL(1);

	/***
	 * NAME
	 *   shutdown - shuts down the underlying tracer provider
	 *
	 * SYNOPSIS
	 *   int (*shutdown)(struct otelc_tracer *tracer, const struct timespec *timeout)
	 *
	 * ARGUMENTS
	 *   tracer  - tracer instance
	 *   timeout - maximum time to wait, or NULL for no limit
	 *
	 * DESCRIPTION
	 *   Shuts down the underlying tracer provider, flushing any buffered
	 *   spans and releasing provider resources.  After shutdown, no further
	 *   spans will be exported.  The optional timeout argument limits how
	 *   long the operation may block.
	 *
	 * RETURN VALUE
	 *   Returns OTELC_RET_OK on success, or OTELC_RET_ERROR on failure.
	 */
	int (*shutdown)(struct otelc_tracer *tracer, const struct timespec *timeout)
		OTELC_NONNULL(1);

	/***
	 * NAME
	 *   start - initializes and starts the tracer instance
	 *
	 * SYNOPSIS
	 *   int (*start)(struct otelc_tracer *tracer)
	 *
	 * ARGUMENTS
	 *   tracer - tracer instance
	 *
	 * DESCRIPTION
	 *   The tracer whose configuration is specified in the OpenTelemetry
	 *   YAML configuration file (set by the previous call to the
	 *   otelc_init() function) is started.  The function initializes the
	 *   tracer in such a way that the following components are initialized
	 *   individually: exporter, sampler, processor and finally provider.
	 *
	 * RETURN VALUE
	 *   Returns OTELC_RET_OK on success, or OTELC_RET_ERROR in case of an
	 *   error.
	 */
	int (*start)(struct otelc_tracer *tracer)
		OTELC_NONNULL_ALL;

	/***
	 * NAME
	 *   destroy - stops the tracer and frees all associated memory
	 *
	 * SYNOPSIS
	 *   void (*destroy)(struct otelc_tracer **tracer)
	 *
	 * ARGUMENTS
	 *   tracer - address of a tracer instance pointer to be stopped and destroyed
	 *
	 * DESCRIPTION
	 *   Stops the tracer and releases all resources and memory associated
	 *   with the tracer instance.
	 *
	 * RETURN VALUE
	 *   This function does not return a value.
	 */
	void (*destroy)(struct otelc_tracer **tracer)
		OTELC_NONNULL_ALL;
};

/***
 * The tracer instance data.
 */
struct otelc_tracer {
	char                          *err;        /* Character array containing the last library error. */
	char                          *scope_name; /* Tracer instrumentation scope name. */
	const struct otelc_tracer_ops *ops;        /* Pointer to the operations vtable. */
};


/***
 * NAME
 *   otelc_tracer_create - creates and returns a new tracer instance
 *
 * SYNOPSIS
 *   struct otelc_tracer *otelc_tracer_create(char **err)
 *
 * ARGUMENTS
 *   err - address of a pointer to store an error message on failure
 *
 * DESCRIPTION
 *   Allocates and initializes a new tracer instance by calling
 *   otel_tracer_new().  On failure, an error message may be written
 *   to *err if provided.
 *
 * RETURN VALUE
 *   Returns a pointer to a newly created tracer instance on success, or nullptr
 *   on failure.
 */
struct otelc_tracer *otelc_tracer_create(char **err);

__CPLUSPLUS_DECL_END
#endif /* OPENTELEMETRY_C_WRAPPER_TRACER_H */

/*
 * Local variables:
 *  c-indent-level: 8
 *  c-basic-offset: 8
 * End:
 *
 * vi: noexpandtab shiftwidth=8 tabstop=8
 */
