Skip to content

Commit

Permalink
feat(proto): add @opentelemetry/proto package
Browse files Browse the repository at this point in the history
  • Loading branch information
dyladan committed Dec 28, 2021
1 parent a35f093 commit c532fd2
Show file tree
Hide file tree
Showing 35 changed files with 7,102 additions and 921 deletions.
3 changes: 3 additions & 0 deletions .gitmodules
Original file line number Diff line number Diff line change
Expand Up @@ -10,3 +10,6 @@
[submodule "experimental/packages/opentelemetry-exporter-metrics-otlp-proto/protos"]
path = experimental/packages/opentelemetry-exporter-metrics-otlp-proto/protos
url = https://github.com/open-telemetry/opentelemetry-proto.git
[submodule "experimental/packages/opentelemetry-proto/opentelemetry-proto"]
path = experimental/packages/opentelemetry-proto/opentelemetry-proto
url = https://github.com/open-telemetry/opentelemetry-proto
Original file line number Diff line number Diff line change
Expand Up @@ -67,6 +67,7 @@
},
"dependencies": {
"@grpc/proto-loader": "^0.6.4",
"@grpc/grpc-js": "^0.6.4",
"@opentelemetry/core": "1.0.1",
"@opentelemetry/exporter-trace-otlp-http": "0.27.0",
"@opentelemetry/resources": "1.0.1",
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -14,56 +14,125 @@
* limitations under the License.
*/

import { Status } from '@grpc/grpc-js/build/src/constants';
import { SpanAttributes } from '@opentelemetry/api';
import { ExportResult, ExportResultCode, getEnv } from '@opentelemetry/core';
import { createExportTraceServiceRequest } from '@opentelemetry/proto';
import { ReadableSpan, SpanExporter } from '@opentelemetry/sdk-trace-base';
import { OTLPExporterNodeBase } from './OTLPExporterNodeBase';
import {
otlpTypes,
toOTLPExportTraceServiceRequest,
OTLPExporterNodeConfigBase,
appendResourcePathToUrlIfNotPresent,
} from '@opentelemetry/exporter-trace-otlp-http';
import { ServiceClientType } from './types';
import { getEnv, baggageUtils } from '@opentelemetry/core';

const DEFAULT_COLLECTOR_RESOURCE_PATH = '/v1/traces';
const DEFAULT_COLLECTOR_URL=`http://localhost:55681${DEFAULT_COLLECTOR_RESOURCE_PATH}`;
import * as http from 'http';
import * as https from 'https';
import { URL } from 'url';

/**
* Collector Trace Exporter for Node with protobuf
*/
export class OTLPTraceExporter
extends OTLPExporterNodeBase<
ReadableSpan,
otlpTypes.opentelemetryProto.collector.trace.v1.ExportTraceServiceRequest
>
implements SpanExporter {
constructor(config: OTLPExporterNodeConfigBase = {}) {
super(config);
this.headers = Object.assign(
this.headers,
baggageUtils.parseKeyPairsIntoRecord(
getEnv().OTEL_EXPORTER_OTLP_TRACES_HEADERS
)
);
}
const DEFAULT_COLLECTOR_PORT = 55681
const DEFAULT_COLLECTOR_RESOURCE_PATH = 'v1/traces';
const DEFAULT_COLLECTOR_HOST = 'localhost';
const DEFAULT_COLLECTOR_PROTOCOL = 'http';

export enum CompressionAlgorithm {
NONE = 'none',
GZIP = 'gzip'
}

export type OTLPTraceExporterOptions = {
keepAlive?: boolean;
compression?: CompressionAlgorithm;
httpAgentOptions?: http.AgentOptions | https.AgentOptions;
headers?: http.OutgoingHttpHeaders;
hostname?: string;
attributes?: SpanAttributes;
url?: string;
concurrencyLimit?: number;
}

convert(
spans: ReadableSpan[]
): otlpTypes.opentelemetryProto.collector.trace.v1.ExportTraceServiceRequest {
return toOTLPExportTraceServiceRequest(spans, this);
export class OTLPTraceExporter implements SpanExporter {
// private _client: TraceServiceClient;
private _url: URL;
private _agent: http.Agent | https.Agent;
private _headers: http.OutgoingHttpHeaders;
private _attributes: SpanAttributes;

constructor(options: OTLPTraceExporterOptions) {
this._url = getURL(options);

const agentOptions = options.httpAgentOptions ?? {};
if (options.keepAlive != null) agentOptions.keepAlive = options.keepAlive;
if (options.concurrencyLimit != null) agentOptions.maxTotalSockets = options.concurrencyLimit;

if (this._url.protocol === 'https') {
this._agent = new https.Agent(agentOptions);
} else if (this._url.protocol === 'http') {
this._agent = new http.Agent(agentOptions);
} else {
throw new Error(`Unknown protocol ${this._url.protocol} in URL ${this._url}`)
}

this._headers = { 'Content-Type': 'application/x-protobuf' };
if (options.headers) {
for (const [header, value] of Object.entries(options.headers)) {
this._headers[header] = value;
}
}

this._attributes = options.attributes ?? {};
}

getDefaultUrl(config: OTLPExporterNodeConfigBase) {
return typeof config.url === 'string'
? config.url
: getEnv().OTEL_EXPORTER_OTLP_TRACES_ENDPOINT.length > 0
? getEnv().OTEL_EXPORTER_OTLP_TRACES_ENDPOINT
: getEnv().OTEL_EXPORTER_OTLP_ENDPOINT.length > 0
? appendResourcePathToUrlIfNotPresent(getEnv().OTEL_EXPORTER_OTLP_ENDPOINT, DEFAULT_COLLECTOR_RESOURCE_PATH)
: DEFAULT_COLLECTOR_URL;
export(spans: ReadableSpan[], resultCallback: (result: ExportResult) => void): void {
const exportTraceServiceRequest = createExportTraceServiceRequest(spans);

if (exportTraceServiceRequest == null) {
setImmediate(() => resultCallback({ code: ExportResultCode.SUCCESS }));
return;
}

// const body = getExportRequestProto()?.encode(message).finish();
const body = exportTraceServiceRequest.serialize();

http.request(this._url, {
agent: this._agent,
headers: this._headers,

})

this._client.Export(exportTraceServiceRequest, (err) => {
if (!err || err.code === Status.OK) {
resultCallback({
code: ExportResultCode.SUCCESS,
});
return;
}

resultCallback({
code: ExportResultCode.FAILED,
error: {
name: err.name,
message: err.message,
},
})
})
}

getServiceClientType() {
return ServiceClientType.SPANS;
async shutdown(): Promise<void> {
// throw new Error("not yet implemented")
this._client.close();
}
}

/**
* Get the URL for the OTLP trace ingest endpoint based on the rules specified at
* https://github.com/open-telemetry/opentelemetry-specification/blob/v1.8.0/specification/protocol/exporter.md
*
* @param config OTLPTraceExporter configuration
* @returns WHATWG URL
*/
function getURL(config: OTLPTraceExporterOptions): URL {
if (typeof config.url === 'string') return new URL(config.url);
if (typeof config.hostname === 'string') return new URL(DEFAULT_COLLECTOR_RESOURCE_PATH, `${DEFAULT_COLLECTOR_PROTOCOL}://${config.hostname}:${DEFAULT_COLLECTOR_PORT}`)

const { OTEL_EXPORTER_OTLP_TRACES_ENDPOINT, OTEL_EXPORTER_OTLP_ENDPOINT } = getEnv();

if (OTEL_EXPORTER_OTLP_TRACES_ENDPOINT.length > 0) return new URL(OTEL_EXPORTER_OTLP_TRACES_ENDPOINT);

if (OTEL_EXPORTER_OTLP_ENDPOINT.length > 0) return new URL(DEFAULT_COLLECTOR_RESOURCE_PATH, OTEL_EXPORTER_OTLP_ENDPOINT);

return new URL(DEFAULT_COLLECTOR_RESOURCE_PATH, `${DEFAULT_COLLECTOR_PROTOCOL}://${DEFAULT_COLLECTOR_HOST}:${DEFAULT_COLLECTOR_PORT}`);
}
Loading

0 comments on commit c532fd2

Please sign in to comment.