Skip to content
Permalink
Browse files
Initial commit
  • Loading branch information
dshafer committed May 13, 2022
0 parents commit 68ca19562d454358ad5c1ce1727caa4c7b7eee01
Showing 13 changed files with 339 additions and 0 deletions.
@@ -0,0 +1,2 @@
FROM node:16
RUN npm install -g ajv-cli
@@ -0,0 +1,11 @@
# Run ajv via a Docker container and bind mount the source files
WORKDIR := /mnt/json-schemas
AJV := docker-compose run --rm -v $${PWD}:$(WORKDIR) -w $(WORKDIR) ajv-cli ajv

# Each schema has its own top-level directory
SCHEMAS := $(shell find . -depth 1 ! -name ".*" -type d | sort)

.PHONY: $(SCHEMAS)
$(SCHEMAS):
$(AJV) test -s $@/$@.schema.json -d "$@/test/invalid-*.json" --invalid ; \
$(AJV) test -s $@/$@.schema.json -d "$@/test/valid-*.json" --valid ; \
@@ -0,0 +1,42 @@
# json-schemas

JSON schemas used by Internet2 Trust & Identity

## Getting Started

To test all schemas, run `make`.

## Contributing

To add a new schema, create a directory structure like the following (where "foo" is the name of the model represented by the schema):

* foo/ - The schema's top-level directory
* test/ - Test examples
* invalid-*.json - Test examples which should be invalid
* valid-*.json - Test examples which should be valid
* foo.schema.json - The schema definition
* README.md - Documentation for the schema

To run validation tests against the schema, run `make foo`.

If you're using Visual Studio Code, you may also want to edit `.vscode/settings.json`, adding an object to the `json.schemas` array that will validate test files using the new schema:

```json
{
"json.schemas": [
...
{
"fileMatch": [
"/foo/test/*.json"
],
"url": "./foo/foo.schema.json"
}
]
}
```

## Background

Validation tests use [ajv-cli](https://github.com/ajv-validator/ajv-cli) via Docker. Refer to `docker-compose.yml` and `.containers/ajv-cli/Dockerfile` for details.

See the [JSON Schema](https://json-schema.org) docuemtation for more information.
@@ -0,0 +1,5 @@
version: "3.8"
services:
ajv-cli:
build:
context: .containers/ajv-cli
@@ -0,0 +1,92 @@
# OpenTelemetry Logs JSON Schema

[JSON schema](https://json-schema.org) for log messages conforming to the [OpenTelemetry Log Data Model](https://opentelemetry.io/docs/reference/specification/logs/data-model/)

## Basic Structure

Each JSON object must contain a `schema` property that specifies the schema name and version it conforms to; currently "edu.internet2.ti.log-1-0-0" is the only acceptable value. The object should also contain a `data` property that includes the relevant log details.

```json
{
"schema": "edu.internet2.ti.log-1-0-0",
"data": { ... }
}
```

## Data Fields

Each property of the `data` object corrresponds to a field in the [OpenTelemetry Log Data Model](https://opentelemetry.io/docs/reference/specification/logs/data-model/). All fields are optional.

### Basic Fields

* [Body](https://opentelemetry.io/docs/reference/specification/logs/data-model/#field-body)
* [SeverityText](https://opentelemetry.io/docs/reference/specification/logs/data-model/#field-severitytext)
* [Timestamp](https://opentelemetry.io/docs/reference/specification/logs/data-model/#field-timestamp)

### Advanced Fields

* [Attributes](https://opentelemetry.io/docs/reference/specification/logs/data-model/#field-attributes)
* [InstrumentationScope](https://opentelemetry.io/docs/reference/specification/logs/data-model/#field-instrumentationscope)
* [ObservedTimestamp](https://opentelemetry.io/docs/reference/specification/logs/data-model/#field-observedtimestamp)
* [Resource](https://opentelemetry.io/docs/reference/specification/logs/data-model/#field-resource)
* [SeverityNumber](https://opentelemetry.io/docs/reference/specification/logs/data-model/#field-severitynumber)

### Trace Context Fields

* [SpanId](https://opentelemetry.io/docs/reference/specification/logs/data-model/#field-spanid)
* [TraceFlags](https://opentelemetry.io/docs/reference/specification/logs/data-model/#field-spanid)
* [TraceId](https://opentelemetry.io/docs/reference/specification/logs/data-model/#field-traceid)

## Examples

This is an example of a basic log message. The `Body` field contains a default Ruby on Rails logger message. Other fields were populated based on information in the `Body`, and the `SeverityNumber` was inferred from the `SeverityText`.

```json
{
"schema": "edu.internet2.ti.log-1-0-0",
"data": {
"Body": "I, [2022-05-06T19:43:31.332218 #1] INFO -- : [ff1cfa6e-3594-44cb-8b71-a42a6cff2b94] Rendered layouts/_iam_integration.erb (0.0ms)",
"SeverityText": "INFO",
"SeverityNumber": 9,
"Timestamp": 1651866211332218000
}
}
```

This is an example of a log message with additional attributes, resource information, and trace context details.

```json
{
"schema": "edu.internet2.ti.log-1-0-0",
"data": {
"Attributes": {
"http.status_code": 500,
"http.url": "http://example.com",
"my.custom.application.tag": "hello"
},
"Body": "20200415T072306-0700 INFO I like donuts",
"Resource": {
"service.name": "donut_shop",
"service.version": "2.0.0",
"k8s.pod.uid": "1138528c-c36e-11e9-a1a7-42010a800198"
},
"SeverityNumber": 9,
"SeverityText": "INFO",
"SpanId": "43222c2d51a7abe3",
"Timestamp": 1586960586000000000,
"TraceId": "f4dbb3edd765f620"
}
}
```

## Roadmap

* Add Resource and Attributes properties based on OpenTelemetry [Resource Semantic Conventions](https://opentelemetry.io/docs/reference/specification/resource/semantic_conventions/), [Log Attribute Semantic Conventions](https://opentelemetry.io/docs/reference/specification/logs/semantic_conventions/), and [Trace Semantic Conventions](https://opentelemetry.io/docs/reference/specification/trace/semantic_conventions/). (These should be generated from the OpenTelemetry schema files; see [Schema File](https://opentelemetry.io/docs/reference/specification/schemas/file_format_v1.0.0/) for details.)

## Background

While OpenTelemetry currently provides SDKs for most languages, the project has initially focused on metrics and tracing, though logging features are slowly being added. In the interim, we need to define, construct, and validate our JSON log messages. Eventually, logging features in the SDKs would presumably make this schema file unnecessary.

The schema version number follows the [SchemaVer](https://docs.snowplowanalytics.com/docs/pipeline-components-and-applications/iglu/common-architecture/schemaver/) draft specification.

For more information about OpenTelemetry's approach to logging, see the [OpenTelemetry Logging Overview](https://opentelemetry.io/docs/reference/specification/logs/overview/).
@@ -0,0 +1,121 @@
{
"$schema": "http://json-schema.org/draft-07/schema",
"$id": "edu.internet2.ti.log-1-0-0",
"$comment": "https://opentelemetry.io/docs/reference/specification/logs/data-model/",
"title": "Logs",
"description": "Internet2 Logs Schema",
"type": "object",
"properties": {
"schema": {
"description": "The schema ID to which this JSON conforms",
"type": "string",
"pattern": "^edu.internet2.ti.log-1-0-0$"
},
"data": {
"type": "object",
"properties": {
"Attributes": {
"description": "Additional information about the event",
"type": "object"
},
"Body": {
"description": "The body of the log record",
"anyOf": [
{
"type": "object"
},
{
"type": "string"
}
],
"examples": [
"test message",
{
"message": "Test message"
}
]
},
"InstrumentationScope": {
"description": "Describes the scope that emitted the log",
"type": "object",
"properties": {
"name": {
"type": "string",
"examples": [
"CustomLogger"
]
},
"version": {
"type": "string",
"examples": [
"0.0.1"
]
}
}
},
"ObservedTimestamp": {
"description": "Time when the event was observed",
"$ref": "#/definitions/timestamp"
},
"Resource": {
"description": "Describes the source of the log",
"type": "object"
},
"SeverityNumber": {
"description": "Numerical value of the severity",
"type": "number",
"minimum": 1,
"maximum": 24,
"examples": [
1,
24
]
},
"SeverityText": {
"description": "The severity text (also known as log level)",
"type": "string",
"examples": [
"TRACE",
"FATAL4"
]
},
"SpanId": {
"description": "Request span id",
"type": "string"
},
"Timestamp": {
"description": "Time when the event occurred",
"$ref": "#/definitions/timestamp"
},
"TraceFlags": {
"description": "W3C trace flag",
"type": "string"
},
"TraceId": {
"description": "Request trace id",
"type": "string"
}
},
"additionalProperties": false
}
},
"required": [
"schema"
],
"additionalProperties": false,
"definitions": {
"timestamp": {
"description": "Nanoseconds since the Unix epoch",
"$ref": "#/definitions/uint64",
"examples": [
1586960586000000000
]
},
"uint64": {
"description": "Unsigned 64-bit integer",
"type": "number",
"minimum": 0,
"maximum": 18446744073709551615
}
}
}
@@ -0,0 +1,6 @@
{
"schema": "edu.internet2.ti.log-1-0-0",
"data": {
"foo": ""
}
}
@@ -0,0 +1,2 @@
{
}
@@ -0,0 +1,4 @@
{
"schema": "edu.internet2.ti.log-1-0-0",
"foo": "bar"
}
@@ -0,0 +1,3 @@
{
"schema": "edu.internet2.ti.logs-1-0-1"
}
@@ -0,0 +1,23 @@
{
"schema": "edu.internet2.ti.log-1-0-0",
"data": {
"Attributes": {
"edu.internet2.schema_name": "logs",
"edu.internet2.schema_version": "1-0-0",
"http.status_code": 500,
"http.url": "http://example.com",
"my.custom.application.tag": "hello"
},
"Body": "20200415T072306-0700 INFO I like donuts",
"Resource": {
"service.name": "donut_shop",
"service.version": "2.0.0",
"k8s.pod.uid": "1138528c-c36e-11e9-a1a7-42010a800198"
},
"TraceId": "f4dbb3edd765f620",
"SpanId": "43222c2d51a7abe3",
"SeverityText": "INFO",
"SeverityNumber": 9,
"Timestamp": 1586960586000000000
}
}
@@ -0,0 +1,13 @@
{
"schema": "edu.internet2.ti.log-1-0-0",
"data": {
"Timestamp": 1586960586000000000,
"Body": {
"i": "am",
"an": "event",
"of": {
"some": "complexity"
}
}
}
}
@@ -0,0 +1,15 @@
{
"schema": "edu.internet2.ti.log-1-0-0",
"data": {
"Timestamp": 1586960586000000000,
"Attributes": {
"http.scheme":"https",
"http.host":"donut.mycie.com",
"http.target":"/order",
"http.method":"post",
"http.status_code":500,
"http.flavor":"1.1",
"http.user_agent": "Mozilla/5.0 (Macintosh; Intel Mac OS X 10_14_0) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/80.0.3987.149 Safari/537.36"
}
}
}

0 comments on commit 68ca195

Please sign in to comment.