Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
1 change: 1 addition & 0 deletions experimental/CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -18,6 +18,7 @@ For notes on migrating to 2.x / 0.200.x see [the upgrade guide](doc/upgrade-to-2

*feat(opentelemetry-configuration): creation of basic ConfigProvider [#5809](https://github.com/open-telemetry/opentelemetry-js/pull/5809) @maryliag
*feat(opentelemetry-configuration): creation of basic FileConfigProvider [#5863](https://github.com/open-telemetry/opentelemetry-js/pull/5863) @maryliag
*feat(opentelemetry-configuration): Parse of Configuration File [#5875](https://github.com/open-telemetry/opentelemetry-js/pull/5875) @maryliag

### :bug: Bug Fixes

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -41,7 +41,8 @@
},
"dependencies": {
"@opentelemetry/api": "^1.9.0",
"@opentelemetry/core": "^2.0.1"
"@opentelemetry/core": "^2.0.1",
"yaml": "^1.10.2"
},
"devDependencies": {
"@opentelemetry/api": "^1.9.0",
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -14,7 +14,6 @@
* limitations under the License.
*/

import { DiagLogLevel } from '@opentelemetry/api';
import {
ConfigurationModel,
initializeDefaultConfiguration,
Expand All @@ -35,12 +34,11 @@ export class EnvironmentConfigProvider implements ConfigProvider {

constructor() {
this._config = initializeDefaultConfiguration();
this._config.disable = getBooleanFromEnv('OTEL_SDK_DISABLED');
this._config.disabled = getBooleanFromEnv('OTEL_SDK_DISABLED');

const logLevel = getStringFromEnv('OTEL_LOG_LEVEL');
const logLevel = diagLogLevelFromString(getStringFromEnv('OTEL_LOG_LEVEL'));
if (logLevel) {
this._config.log_level =
diagLogLevelFromString(logLevel) ?? DiagLogLevel.INFO;
this._config.log_level = logLevel;
}

const nodeResourceDetectors = getStringListFromEnv(
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -14,19 +14,25 @@
* limitations under the License.
*/

import { getStringFromEnv } from '@opentelemetry/core';
import {
diagLogLevelFromString,
getStringFromEnv,
getStringListFromEnv,
} from '@opentelemetry/core';
import {
ConfigurationModel,
initializeDefaultConfiguration,
} from './configModel';
import { ConfigProvider } from './IConfigProvider';
import * as fs from 'fs';
import * as yaml from 'yaml';

export class FileConfigProvider implements ConfigProvider {
private _config: ConfigurationModel;

constructor() {
this._config = initializeDefaultConfiguration();
ParseConfigFile(this._config);
}

getInstrumentationConfig(): ConfigurationModel {
Expand All @@ -37,7 +43,10 @@ export class FileConfigProvider implements ConfigProvider {
export function hasValidConfigFile(): boolean {
const configFile = getStringFromEnv('OTEL_EXPERIMENTAL_CONFIG_FILE');
if (configFile) {
if (!configFile.endsWith('.yaml') || !fs.existsSync(configFile)) {
if (
!(configFile.endsWith('.yaml') || configFile.endsWith('.yml')) ||
!fs.existsSync(configFile)
) {
throw new Error(
`Config file ${configFile} set on OTEL_EXPERIMENTAL_CONFIG_FILE is not valid`
);
Expand All @@ -46,3 +55,92 @@ export function hasValidConfigFile(): boolean {
}
return false;
}

function ParseConfigFile(config: ConfigurationModel) {
const supportedFileVersions = ['1.0-rc.1'];
const configFile = getStringFromEnv('OTEL_EXPERIMENTAL_CONFIG_FILE') || '';
const file = fs.readFileSync(configFile, 'utf8');
const parsedContent = yaml.parse(file);

if (
parsedContent['file_format'] &&
supportedFileVersions.includes(parsedContent['file_format'])
) {
const disabled = getValue(config.disabled, parsedContent['disabled']);
if (disabled || disabled === false) {
config.disabled = disabled;
}

const logLevel = getValue(
config.log_level,
diagLogLevelFromString(parsedContent['log_level'])
);
if (logLevel) {
config.log_level = logLevel;
}

const attrList = getValue(
config.resource.attributes_list,
parsedContent['resource']?.['attributes_list']
);
if (attrList) {
config.resource.attributes_list = attrList;
}

const schemaUrl = getValue(
config.resource.schema_url,
parsedContent['resource']?.['schema_url']
);
if (schemaUrl) {
config.resource.schema_url = schemaUrl;
}

setResourceAttributes(config, parsedContent['resource']?.['attributes']);

setValuesFromEnvVariables(config);
} else {
throw new Error(
`Unsupported File Format: ${parsedContent['file_format']}. It must be one of the following: ${supportedFileVersions}`
);
}
}

// eslint-disable-next-line @typescript-eslint/no-explicit-any
function getValue(obj: unknown, value: unknown): any {
if (typeof obj === 'boolean') {
const raw = String(value)?.trim().toLowerCase();
if (raw === 'false') {
return false;
}
}
return value;
}

/**
* Some values can only be set by Environment Variables and
* not declarative configuration. This function set those values.
* @param config
*/
function setValuesFromEnvVariables(config: ConfigurationModel) {
const nodeResourceDetectors = getStringListFromEnv(
'OTEL_NODE_RESOURCE_DETECTORS'
);
if (nodeResourceDetectors) {
config.node_resource_detectors = nodeResourceDetectors;
}
}

// eslint-disable-next-line @typescript-eslint/no-explicit-any
function setResourceAttributes(config: ConfigurationModel, attributes: any[]) {
if (attributes) {
config.resource.attributes = [];
for (let i = 0; i < attributes.length; i++) {
const att = attributes[i];
config.resource.attributes.push({
name: att['name'],
value: att['value'],
type: att['type'] ?? 'string',
});
}
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -21,7 +21,7 @@ export interface ConfigurationModel {
* Configure if the SDK is disabled or not.
* If omitted or null, false is used.
*/
disable: boolean;
disabled: boolean;

/**
* Configure the log level of the internal logger used by the SDK.
Expand All @@ -44,7 +44,7 @@ export interface ConfigurationModel {

export function initializeDefaultConfiguration(): ConfigurationModel {
const config: ConfigurationModel = {
disable: false,
disabled: true,
log_level: DiagLogLevel.INFO,
node_resource_detectors: ['all'],
resource: {},
Expand All @@ -56,7 +56,7 @@ export function initializeDefaultConfiguration(): ConfigurationModel {
export interface ConfigAttributes {
name: string;
value: string | boolean | number | string[] | boolean[] | number[];
type?:
type:
| 'string'
| 'bool'
| 'int'
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -20,12 +20,69 @@ import { DiagLogLevel } from '@opentelemetry/api';
import { createConfigProvider } from '../src/ConfigProvider';

const defaultConfig: Configuration = {
disable: false,
disabled: false,
log_level: DiagLogLevel.INFO,
node_resource_detectors: ['all'],
resource: {},
};

const configFromFile: Configuration = {
disabled: false,
log_level: DiagLogLevel.DEBUG,
node_resource_detectors: ['all'],
resource: {
schema_url: 'https://opentelemetry.io/schemas/1.16.0',
attributes_list: 'service.namespace=my-namespace,service.version=1.0.0',
attributes: [
{
name: 'service.name',
value: 'unknown_service',
type: 'string',
},
{
name: 'string_key',
value: 'value',
type: 'string',
},
{
name: 'bool_key',
value: true,
type: 'bool',
},
{
name: 'int_key',
value: 1,
type: 'int',
},
{
name: 'double_key',
value: 1.1,
type: 'double',
},
{
name: 'string_array_key',
value: ['value1', 'value2'],
type: 'string_array',
},
{
name: 'bool_array_key',
value: [true, false],
type: 'bool_array',
},
{
name: 'int_array_key',
value: [1, 2],
type: 'int_array',
},
{
name: 'double_array_key',
value: [1.1, 2.2],
type: 'double_array',
},
],
},
};

describe('ConfigProvider', function () {
describe('get values from environment variables', function () {
afterEach(function () {
Expand All @@ -47,7 +104,7 @@ describe('ConfigProvider', function () {
process.env.OTEL_SDK_DISABLED = 'true';
const expectedConfig: Configuration = {
...defaultConfig,
disable: true,
disabled: true,
};
const configProvider = createConfigProvider();
assert.deepStrictEqual(
Expand Down Expand Up @@ -103,6 +160,7 @@ describe('ConfigProvider', function () {
describe('get values from config file', function () {
afterEach(function () {
delete process.env.OTEL_EXPERIMENTAL_CONFIG_FILE;
delete process.env.OTEL_NODE_RESOURCE_DETECTORS;
});

it('should initialize config with default values from valid config file', function () {
Expand All @@ -111,7 +169,7 @@ describe('ConfigProvider', function () {
const configProvider = createConfigProvider();
assert.deepStrictEqual(
configProvider.getInstrumentationConfig(),
defaultConfig
configFromFile
);
});

Expand All @@ -122,6 +180,13 @@ describe('ConfigProvider', function () {
});
});

it('should return error from invalid config file format', function () {
process.env.OTEL_EXPERIMENTAL_CONFIG_FILE = 'test/fixtures/invalid.yaml';
assert.throws(() => {
createConfigProvider();
});
});

it('should initialize config with default values with empty string for config file', function () {
process.env.OTEL_EXPERIMENTAL_CONFIG_FILE = '';
const configProvider = createConfigProvider();
Expand All @@ -139,5 +204,30 @@ describe('ConfigProvider', function () {
defaultConfig
);
});

it('should initialize config with default values from valid short config file', function () {
process.env.OTEL_EXPERIMENTAL_CONFIG_FILE =
'test/fixtures/short-config.yml';
const configProvider = createConfigProvider();
assert.deepStrictEqual(
configProvider.getInstrumentationConfig(),
defaultConfig
);
});

it('should initialize config with default values from valid config file and node resources', function () {
process.env.OTEL_EXPERIMENTAL_CONFIG_FILE =
'test/fixtures/short-config.yml';
process.env.OTEL_NODE_RESOURCE_DETECTORS = 'env,host, serviceinstance';
const expectedConfig = {
...defaultConfig,
node_resource_detectors: ['env', 'host', 'serviceinstance'],
};
const configProvider = createConfigProvider();
assert.deepStrictEqual(
configProvider.getInstrumentationConfig(),
expectedConfig
);
});
});
});
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
file_format: "invalid"
Original file line number Diff line number Diff line change
Expand Up @@ -14,7 +14,7 @@ file_format: "1.0-rc.1"
disabled: false
# Configure the log level of the internal logger used by the SDK.
# If omitted, info is used.
log_level: info
log_level: debug
# Configure general attribute limits. See also tracer_provider.limits, logger_provider.limits.
attribute_limits:
# Configure max attribute value size.
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,2 @@
file_format: "1.0-rc.1"
disabled: false
10 changes: 5 additions & 5 deletions package-lock.json

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

Loading