blob: 0378c575d31d169e473711b960378def9099a842 [file] [log] [blame]
/**
* Licensed to the Apache Software Foundation (ASF) under one
* or more contributor license agreements. See the NOTICE file
* distributed with this work for additional information
* regarding copyright ownership. The ASF licenses this file
* to you 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 APACHE_HTRACE_HTRACE_HPP
#define APACHE_HTRACE_HTRACE_HPP
#include "htrace.h"
#include <string>
/**
* The public C++ API for the HTrace native client.
*
* The C++ API is a wrapper around the C API. The advantage of this is that we
* can change the C++ API in this file without breaking binary compatibility.
*
* EXCEPTIONS
* We do not use exceptions in this API. This code should be usable by
* libraries and applications that are using the Google C++ coding style.
* The one case where we do use exceptions is to translate NULL pointer returns
* on OOM into std::bad_alloc exceptions. In general, it is extremely unlikely
* that the size of memory allocations we are doing will produce OOM. Most
* C++ programs do not attempt to handle OOM anyway because of the extra code
* complexity that would be required. So translating this into an exception is
* fine.
*
* C++11
* This code should not require C++11. We might add #ifdefs later to take
* advantage of certain C++11 or later features if they are available.
*/
namespace htrace {
class Sampler;
class Scope;
class Tracer;
/**
* An HTrace Configuration object.
*
* Configurations are thread-safe. They can be used by multiple threads
* simultaneously.
*/
class Conf {
public:
/**
* Create a new HTrace Conf.
*
* @param values A configuration string containing a series of
* semicolon-separated key=value entries.
* We do not hold on to a reference to this string.
* @param defaults Another semicolon-separated set of key=value entries.
* The defaults to be used when there is no corresponding
* value in 'values.' We do not hold on to a reference to
* this string.
*/
Conf(const char *values)
: conf_(htrace_conf_from_str(values))
{
if (!conf_) {
throw std::bad_alloc();
}
}
Conf(const std::string &values)
: conf_(htrace_conf_from_str(values.c_str()))
{
if (!conf_) {
throw std::bad_alloc();
}
}
~Conf() {
htrace_conf_free(conf_);
conf_ = NULL;
}
private:
friend class Tracer;
friend class Sampler;
Conf &operator=(Conf &other); // Can't copy
Conf(Conf &other);
struct htrace_conf *conf_;
};
/**
* An HTrace context object.
*
* Contexts are thread-safe. They can be used by multiple threads simultaneoy
* Most applications will not need more than one HTrace context, which is
* often global (or at least widely used.)
*/
class Tracer {
public:
/**
* Create a new Tracer.
*
* @param name The name of the tracer to create. We do not hold on to a
* reference to this string.
* @param conf The configuration to use for the new tracer. We do not
* hold on to a reference to this configuration.
*/
Tracer(const std::string &name, const Conf &conf)
: tracer_(htracer_create(name.c_str(), conf.conf_))
{
if (!tracer_) {
throw std::bad_alloc();
}
}
std::string Name() {
return std::string(htracer_tname(tracer_));
}
/**
* Free the Tracer.
*
* This destructor must not be called until all the other objects which hold
* a reference (such as samplers and trace scopes) are freed. It is often
* not necessary to destroy this object at all unless you are writing a
* library and want to support unloading your library, or you are writing an
* application and want to support some kind of graceful shutdown.
*
* We could make this friendlier with some kind of reference counting via
* atomic variables, but only at the cost of reduced performance.
*/
~Tracer() {
htracer_free(tracer_);
tracer_ = NULL;
}
private:
friend class Sampler;
friend class Scope;
Tracer(const Tracer &other); // Can't copy
const Tracer &operator=(const Tracer &other);
struct htracer *tracer_;
};
/**
* An HTrace sampler.
*
* Samplers determine when new spans are created.
* See htrace.h for more information.
*
* Samplers are thread-safe. They can be used by multiple threads
* simultaneously.
*/
class Sampler {
public:
/**
* Create a new Sampler.
*
* @param tracer The tracer to use. You must not free this tracer until
* after this sampler is freed.
* @param conf The configuration to use for the new sampler. We do not
* hold on to a reference to this configuration.
*/
Sampler(Tracer *tracer, const Conf &conf)
: smp_(htrace_sampler_create(tracer->tracer_, conf.conf_)) {
if (!smp_) {
throw std::bad_alloc();
}
}
/**
* Get a description of this Sampler.
*/
std::string ToString() {
return std::string(htrace_sampler_to_str(smp_));
}
~Sampler() {
htrace_sampler_free(smp_);
smp_ = NULL;
}
private:
friend class Tracer;
friend class Scope;
Sampler(const Sampler &other); // Can't copy
const Sampler &operator=(const Sampler &other);
struct htrace_sampler *smp_;
};
class Scope {
public:
Scope(Tracer &tracer, const char *name)
: scope_(htrace_start_span(tracer.tracer_, NULL, name)) {
}
Scope(Tracer &tracer, const std::string &name)
: scope_(htrace_start_span(tracer.tracer_, NULL, name.c_str())) {
}
Scope(Tracer &tracer, Sampler &smp, const char *name)
: scope_(htrace_start_span(tracer.tracer_, smp.smp_, name)) {
}
Scope(Tracer &tracer, Sampler &smp, const std::string &name)
: scope_(htrace_start_span(tracer.tracer_, smp.smp_, name.c_str())) {
}
~Scope() {
htrace_scope_close(scope_);
scope_ = NULL;
}
private:
friend class Tracer;
Scope(htrace::Scope &other); // Can't copy
Scope& operator=(Scope &scope); // Can't assign
struct htrace_scope *scope_;
};
}
#endif
// vim: ts=2:sw=2:et