mirror of https://github.com/cloudevents/spec.git
Compare commits
492 Commits
Author | SHA1 | Date |
---|---|---|
|
4ad3223f05 | |
|
40cda2e99d | |
|
6749e1fda2 | |
|
177d4fe98f | |
|
e2d119e26d | |
|
e007e0aecb | |
|
11da3778f3 | |
|
c5eb14ae13 | |
|
a43f83658e | |
|
94c622d44a | |
|
3fd0012454 | |
|
c932302d7a | |
|
5f90878705 | |
|
67163e50ef | |
|
24ad80a58e | |
|
43f1c5359c | |
|
8f8770737c | |
|
8386fa6743 | |
|
37545bfcc8 | |
|
2e9e677f1d | |
|
a31214efab | |
|
721144c759 | |
|
f65302fb7c | |
|
b5dc5ffd3e | |
|
a85940fc1e | |
|
8c54946e50 | |
|
fdab0b5c29 | |
|
0ce5ea4163 | |
|
fbb00366d6 | |
|
d130533898 | |
|
fed55696ea | |
|
b1643cf6f9 | |
|
68902074ee | |
|
0c377f7cae | |
|
b131f9725c | |
|
0dad249627 | |
|
8463221d42 | |
|
7f06c5c5c9 | |
|
dc521c077d | |
|
8c0111f18e | |
|
45026679ee | |
|
beb886aa65 | |
|
6e33dd6b62 | |
|
9642361f6e | |
|
b86ed0a917 | |
|
04a47b7991 | |
|
e1b4f2c5ea | |
|
25fa60b04e | |
|
dc92e423fd | |
|
6ed43691d8 | |
|
96134ee30b | |
|
93565f4ae8 | |
|
6374c6fca7 | |
|
b20cf0ac60 | |
|
82c16f63a0 | |
|
6e6e66555f | |
|
ed8a2cf38b | |
|
d3bca3adee | |
|
b489a71654 | |
|
33836c17ff | |
|
c28210f963 | |
|
c0927d1234 | |
|
7204b18328 | |
|
e30acf32d0 | |
|
66c067b38b | |
|
0be71570ca | |
|
e79d7b2cc3 | |
|
d697a87692 | |
|
ecb2721ea6 | |
|
1f00ea507a | |
|
b17f24f88f | |
|
bf4b4a4c68 | |
|
ba201fa728 | |
|
561c5e5401 | |
|
a15821bd34 | |
|
23abcc4f41 | |
|
55b53febda | |
|
cb26319369 | |
|
83a8bd9150 | |
|
03aba4adc0 | |
|
900900ccfd | |
|
285dc27c7f | |
|
ddc8be19e3 | |
|
0dc5d9534d | |
|
e9b3aafef5 | |
|
b9292aaaf4 | |
|
003ad3a35c | |
|
c859ad54d5 | |
|
db633018e8 | |
|
3f7a33d7b9 | |
|
ad2ff88a69 | |
|
efc45dbaaa | |
|
b087efc69d | |
|
a900ac699c | |
|
3ff0462b37 | |
|
5fadd5536e | |
|
c9bd350fcb | |
|
4c5fea9368 | |
|
146330f6c1 | |
|
d80c7c67f9 | |
|
f1db8a4600 | |
|
800f5a2b12 | |
|
d2e6980c7e | |
|
e0b3078c18 | |
|
130ba0d183 | |
|
758a53321e | |
|
8664a5245e | |
|
43afbf55ca | |
|
a7f82aae72 | |
|
6cc94acabc | |
|
35eaaae5e9 | |
|
d0eccd083b | |
|
9730d8ee0b | |
|
c48be59daf | |
|
a04f46e613 | |
|
4580f01bcd | |
|
660507801d | |
|
755e45863e | |
|
24511af714 | |
|
2d64459093 | |
|
7f0d456c6d | |
|
0707b856fe | |
|
a64cb14ae6 | |
|
8d87dfbb91 | |
|
4ce357422d | |
|
ec3309ea9c | |
|
563a63c300 | |
|
6f0ea0a0a4 | |
|
777d0c0398 | |
|
b3a66bebdd | |
|
678f21f067 | |
|
f5046fcbcd | |
|
d95b24bbfe | |
|
306daeb0c7 | |
|
fc50d7fb36 | |
|
48b2183c1d | |
|
f5c9723f73 | |
|
1d111b4900 | |
|
3fc733d435 | |
|
d8ed86c347 | |
|
b1f64f3598 | |
|
09b4b31bfb | |
|
3925a70770 | |
|
17315636aa | |
|
5a32a5b459 | |
|
3223a785c7 | |
|
b0c232bd4f | |
|
7336bff183 | |
|
2b9a7af2ff | |
|
788669c018 | |
|
503dec6ab2 | |
|
9a6c61349d | |
|
84cc657be7 | |
|
66e625a551 | |
|
14a849fdcf | |
|
48e2cd9eed | |
|
cf678e6247 | |
|
b20954deb3 | |
|
12336bbb48 | |
|
3877083f83 | |
|
4afee21c6c | |
|
59050ce2ea | |
|
4c4bf3552b | |
|
27db799628 | |
|
e660f244e0 | |
|
9b440f3ac9 | |
|
56ef6fdba4 | |
|
b43a64bf4f | |
|
1a474ad704 | |
|
43c1f10542 | |
|
fc1c947ba6 | |
|
3687a28ff2 | |
|
666a123157 | |
|
4af4b73585 | |
|
855b1c0749 | |
|
ec8a0e48f3 | |
|
b90ce7809f | |
|
e9c982ac9d | |
|
1c2fa2b571 | |
|
1e9cc9543c | |
|
ca680d3be4 | |
|
6c27a7e613 | |
|
e7b9d8e76f | |
|
ca27a62cc6 | |
|
9e7d4fe210 | |
|
566bd1d1cc | |
|
6571702611 | |
|
7382de6d8f | |
|
525210bb6a | |
|
71ae904981 | |
|
8e7712024d | |
|
882134a449 | |
|
6657606d86 | |
|
d719e48819 | |
|
ba91abf6db | |
|
735f261858 | |
|
89f61cfcbf | |
|
255e258d61 | |
|
d3dba82879 | |
|
243a988d32 | |
|
40a2c17818 | |
|
ca2594f2bc | |
|
6ab8778911 | |
|
bc77ae3463 | |
|
c4f0e68a37 | |
|
e3be9b17f8 | |
|
32f075f69c | |
|
551e01782c | |
|
4ef49059cc | |
|
3da5643ebc | |
|
fc7d09c5c8 | |
|
927dbdaa03 | |
|
064733d258 | |
|
b6b144114c | |
|
ba963c8770 | |
|
8f1877fab7 | |
|
0862210796 | |
|
6c542c8309 | |
|
fa8450b2e4 | |
|
c9856cef7d | |
|
da56f7eb2d | |
|
29ceca85f9 | |
|
efa966d6d7 | |
|
bc3ff47787 | |
|
d775bc17bc | |
|
1459a63c0a | |
|
65960ff5f4 | |
|
5f073bf7a7 | |
|
86494f360a | |
|
2b9873a3cf | |
|
2e09394c62 | |
|
c6811c7a65 | |
|
019a339c5b | |
|
7820621abb | |
|
ff5139fb85 | |
|
721fd84e49 | |
|
ac7b29197f | |
|
5938841bcf | |
|
8f36d46767 | |
|
0e4d8afd44 | |
|
51f86048c1 | |
|
d3606565bc | |
|
676cef9167 | |
|
17339b2d51 | |
|
25295a53c4 | |
|
1efd5f3ee6 | |
|
ec2feddc53 | |
|
d1d6617f02 | |
|
fe4e30828e | |
|
6701c68178 | |
|
9a01c4ce17 | |
|
5ae8d30c5f | |
|
5545d0196b | |
|
4966aed49d | |
|
a2f61947e7 | |
|
c47f355d9a | |
|
6ac14dc8cd | |
|
d9761b9e45 | |
|
48fdf103bf | |
|
d28117c3fd | |
|
8e78fcafa0 | |
|
a6921722f4 | |
|
cb7f0376e8 | |
|
65ec76de84 | |
|
fd720c7330 | |
|
d8fe24c785 | |
|
ab0b385913 | |
|
be63f8811f | |
|
98ae14b989 | |
|
f17c248aa3 | |
|
604fef3eea | |
|
32507d1c90 | |
|
0ace88a7f8 | |
|
9b3a3c9449 | |
|
0f46a2fe80 | |
|
c71e4fe007 | |
|
cec773e9ef | |
|
6cd09e5e21 | |
|
06aab847ec | |
|
bbd0ca93d4 | |
|
0284b8c5e1 | |
|
69dfe0d52c | |
|
9ea4ef4515 | |
|
f0d4bbe5d4 | |
|
11de4345a9 | |
|
e01f9779c6 | |
|
cc1bc00ad4 | |
|
caa22d49be | |
|
f5df39dbc3 | |
|
fc99a2a36b | |
|
c2af79d7d5 | |
|
9b0fce278e | |
|
dbd5df0a70 | |
|
ff63dd9a6d | |
|
a6111d2f6a | |
|
3cffde5f0c | |
|
f80c3bd540 | |
|
650f3e5265 | |
|
213ba54f4e | |
|
5be731125d | |
|
8dfd51183d | |
|
7953cd1bd4 | |
|
bcdbbba805 | |
|
f9b9363920 | |
|
54edbc6f4c | |
|
e44d7a826f | |
|
7d71b3e8fa | |
|
6559d1fea3 | |
|
284e82c60e | |
|
cc8fdf5f1f | |
|
bad81171bd | |
|
a10d1b1422 | |
|
80cb160a67 | |
|
898faca29f | |
|
618fc10e54 | |
|
98f1cf4102 | |
|
eba91e8ddd | |
|
e9a0686370 | |
|
a685097a18 | |
|
355c85f8bb | |
|
740d4665f9 | |
|
ab05c30520 | |
|
f6b83137eb | |
|
b104f2a65a | |
|
26876ac168 | |
|
0afe766be7 | |
|
3b5f5d5d76 | |
|
fd8251359d | |
|
97623252cd | |
|
84322e680a | |
|
dc30b6134f | |
|
e6eadb7335 | |
|
1eac143970 | |
|
5e5ef9a9ba | |
|
5343093f54 | |
|
b95f2ee2a8 | |
|
b2b0541776 | |
|
f5248f433b | |
|
949f035414 | |
|
d5dc968fb7 | |
|
d44e52a7e1 | |
|
6aa22d1781 | |
|
e7a5ded252 | |
|
4555520b17 | |
|
61260bdc72 | |
|
00d2681e6d | |
|
ab765d132e | |
|
27952ff35d | |
|
da73ca7a79 | |
|
9a226340d1 | |
|
67f16bb0a8 | |
|
834b3e768a | |
|
2c361faafd | |
|
f5cc7374f6 | |
|
8b6072f1af | |
|
fa1d3b3cc2 | |
|
8031711d87 | |
|
53ca7ed935 | |
|
aadf0cfd48 | |
|
eadef20ff7 | |
|
bd9cd1e419 | |
|
b9cac86242 | |
|
f9485e9767 | |
|
2cf99bc718 | |
|
8e129e4ff3 | |
|
18d5870b2b | |
|
186d26230b | |
|
7bd28f7d81 | |
|
e661fa7ec8 | |
|
6ca6d5add2 | |
|
6de2a310dd | |
|
417a9d1d25 | |
|
1deb463644 | |
|
7a556d84ef | |
|
e4aeb49891 | |
|
b390b08e17 | |
|
d38d1218ed | |
|
4a211bcc0b | |
|
86e52fae5c | |
|
f02c85ee7f | |
|
a6c937bcf0 | |
|
39c12dc36a | |
|
3b346bf3e0 | |
|
44472e84b6 | |
|
061eeecabc | |
|
0b54da356a | |
|
a706625010 | |
|
46df43f916 | |
|
3cb4ed42e4 | |
|
94b57f46e9 | |
|
faf7053847 | |
|
919367fdae | |
|
dac282d409 | |
|
8446adc241 | |
|
903fbe0038 | |
|
9d437246be | |
|
43af063965 | |
|
5ef772348f | |
|
3516bf85ac | |
|
36499de398 | |
|
2e281849ea | |
|
560ec3275c | |
|
875c05f568 | |
|
45edce67ee | |
|
1d6a58a038 | |
|
fa43cafc40 | |
|
9532ba7e3b | |
|
3d46116ddb | |
|
aa5eee5b1f | |
|
6febe44d8d | |
|
1dfd6358d6 | |
|
1097f036e1 | |
|
c5ccc88c9b | |
|
b7a5fa47c9 | |
|
5d65653440 | |
|
420a235b95 | |
|
c812a2ef0e | |
|
3c868b646c | |
|
d4803d8ef3 | |
|
236d642bc4 | |
|
11fbeab7de | |
|
35e473e2a7 | |
|
7e03471f5e | |
|
9885f4da39 | |
|
73b5490ac5 | |
|
d75a89cebf | |
|
add3a759fd | |
|
e660bb04c7 | |
|
19aa07a4d7 | |
|
f7e2cec949 | |
|
154afe54a4 | |
|
cbd1a3aee9 | |
|
d90d1d75a5 | |
|
765283e290 | |
|
9fc00efae9 | |
|
00e26c279e | |
|
03586530a8 | |
|
a69e39c81b | |
|
d9996d470e | |
|
5195f6c29e | |
|
58eeed8719 | |
|
218c8ccdef | |
|
ae6ec21d59 | |
|
cc21bec87c | |
|
ca5bc52220 | |
|
6eb8b9f4bf | |
|
4823a38509 | |
|
4e67fb45a4 | |
|
2bcfe616f9 | |
|
ad67a8972a | |
|
27a6b036b1 | |
|
9f36a56037 | |
|
35a9fb26b3 | |
|
01d02e4270 | |
|
38acd076e0 | |
|
2fdf52f432 | |
|
9bba3ad41a | |
|
c1aca4e3b2 | |
|
8ef36d3e1a | |
|
1d63265288 | |
|
c9e5508208 | |
|
e226e67125 | |
|
90a3f9f330 | |
|
8ab5b2ea22 | |
|
8383b3b67f | |
|
055ed6c551 | |
|
5eab4a2536 | |
|
f97960bddd | |
|
2bc326c00d | |
|
62b0958ecc | |
|
3962df7f75 | |
|
a96b8273fc | |
|
9f6cbda9e4 | |
|
3e0489069f | |
|
f4c1b5f03b | |
|
30b1b9a80f | |
|
48056e22ae | |
|
163c499860 | |
|
778874c795 | |
|
e48ee90d44 | |
|
6e40dd92f1 | |
|
cedf688f9f | |
|
09f6157fbe | |
|
1da1329fd8 | |
|
63f337a6a8 | |
|
09ef41776e | |
|
1ea5aede25 | |
|
41559e48aa | |
|
455f2ef28d | |
|
4a4aa2b5d0 | |
|
9de800fedf | |
|
f9066b3f6e |
|
@ -0,0 +1,8 @@
|
|||
# CLOMonitor metadata file
|
||||
# This file must be located at the root of the repository
|
||||
|
||||
# Checks exemptions
|
||||
exemptions:
|
||||
- check: analytics
|
||||
reason: "Can't add analytics to markdown"
|
||||
|
|
@ -0,0 +1,2 @@
|
|||
# Force shell scripts to be LF on checkout to support executing on Windows WSL.
|
||||
*.sh text eol=lf
|
|
@ -0,0 +1 @@
|
|||
blank_issues_enabled: false
|
|
@ -0,0 +1,34 @@
|
|||
---
|
||||
name: New issue
|
||||
about: 'Create a new issue'
|
||||
title: ''
|
||||
labels: ''
|
||||
assignees: ''
|
||||
|
||||
---
|
||||
(Please remove the text below after reading it.)
|
||||
|
||||
When filing an issue in this repository, please consider the following:
|
||||
|
||||
- Is this:
|
||||
- A feature request for a new form of integration etc?
|
||||
- A report of a technical issue with the existing spec?
|
||||
- A suggestion for improving the clarity of the existing spec
|
||||
(even if it's not "wrong" as such)?
|
||||
- Something else?
|
||||
- Is there context behind your request that would be useful for readers to
|
||||
understand? (There's no need to go into huge amounts of detail, but a few
|
||||
sentences about the motivation can be really helpful.)
|
||||
- Do you know *roughly* what you'd expect a change to address this issue would
|
||||
look like? If so, it's useful to create a PR at the same time, linking to
|
||||
the issue. This doesn't need to be polished and ready to merge - it's just to
|
||||
help clarify roughly what you're considering.
|
||||
|
||||
If the issue is requires discussion, it's really useful if you're able to
|
||||
attend the weekly working group meeting as described
|
||||
[here](https://github.com/cloudevents/spec/?tab=readme-ov-file#meeting-time).
|
||||
Often a discussion which would take multiple back-and-forth comments on an
|
||||
issue can be resolved with a few minutes of conversation. We understand the
|
||||
timing may not be convenient for everyone - please let us know if that's the
|
||||
case, and we can potentially arrange something with the most relevant group
|
||||
members at a more convenient time.
|
|
@ -0,0 +1,20 @@
|
|||
Fixes #
|
||||
|
||||
<!-- Please include the 'why' behind your changes if no issue exists -->
|
||||
|
||||
## Proposed Changes
|
||||
|
||||
-
|
||||
-
|
||||
-
|
||||
|
||||
**Release Note**
|
||||
|
||||
<!--
|
||||
If this change has user-visible impact, write a release note in the block
|
||||
below. If this change has no user-visible impact, no release note is needed.
|
||||
-->
|
||||
|
||||
```release-note
|
||||
|
||||
```
|
|
@ -0,0 +1,91 @@
|
|||
# Copyright 2021 The CloudEvents Authors.
|
||||
# Copyright 2020 The Knative Authors.
|
||||
#
|
||||
# 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.
|
||||
|
||||
name: 'Release Notes'
|
||||
|
||||
on:
|
||||
workflow_dispatch:
|
||||
inputs:
|
||||
branch:
|
||||
description: 'Branch? (master)'
|
||||
required: true
|
||||
default: 'master'
|
||||
start-sha:
|
||||
description: 'Starting SHA? (last tag on branch)'
|
||||
end-sha:
|
||||
description: 'Ending SHA? (latest HEAD)'
|
||||
|
||||
jobs:
|
||||
release-notes:
|
||||
name: Release Notes
|
||||
runs-on: 'ubuntu-latest'
|
||||
|
||||
env:
|
||||
GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
|
||||
|
||||
steps:
|
||||
- name: Set up Go
|
||||
uses: actions/setup-go@v2
|
||||
|
||||
- name: Install Dependencies
|
||||
run: GO111MODULE=on go get k8s.io/release/cmd/release-notes
|
||||
|
||||
- name: Check out code
|
||||
uses: actions/checkout@v2
|
||||
with:
|
||||
fetch-depth: 0
|
||||
|
||||
# Note: Defaults needs to run after we check out the repo.
|
||||
- name: Defaults
|
||||
run: |
|
||||
echo ORG=$(echo '${{ github.repository }}' | awk -F '/' '{print $1}') >> $GITHUB_ENV
|
||||
echo REPO=$(echo '${{ github.repository }}' | awk -F '/' '{print $2}') >> $GITHUB_ENV
|
||||
|
||||
echo "BRANCH=${{ github.event.inputs.branch }}" >> $GITHUB_ENV
|
||||
|
||||
if [[ "${{ github.event.inputs.start-sha }}" != "" ]]; then
|
||||
echo "START_SHA=${{ github.event.inputs.start-sha }}" >> $GITHUB_ENV
|
||||
else
|
||||
# Default Starting SHA (thanks @dprotaso)
|
||||
export semver=$(git describe --match "v[0-9]*" --abbrev=0)
|
||||
echo "Using ${semver} tag for starting sha."
|
||||
echo START_SHA=$(git rev-list -n 1 "${semver}") >> $GITHUB_ENV
|
||||
fi
|
||||
|
||||
if [[ "${{ github.event.inputs.end-sha }}" != "" ]]; then
|
||||
echo "END_SHA=${{ github.event.inputs.end-sha }}" >> $GITHUB_ENV
|
||||
else
|
||||
# Default Ending SHA (thanks @dprotaso)
|
||||
echo "END_SHA=$(git rev-list -n 1 HEAD)" >> $GITHUB_ENV
|
||||
fi
|
||||
|
||||
- name: Generate Notes
|
||||
run: |
|
||||
# See https://github.com/kubernetes/release/tree/master/cmd/release-notes for options.
|
||||
# Note: we are setting env vars in the Defaults step.
|
||||
release-notes \
|
||||
--required-author "" \
|
||||
--repo-path "$(pwd)" \
|
||||
--output release-notes.md
|
||||
|
||||
- name: Display Notes
|
||||
run: |
|
||||
cat release-notes.md
|
||||
|
||||
- name: Archive Release Notes
|
||||
uses: actions/upload-artifact@v2
|
||||
with:
|
||||
name: release-notes.md
|
||||
path: release-notes.md
|
|
@ -6,4 +6,15 @@ jobs:
|
|||
runs-on: ubuntu-latest
|
||||
steps:
|
||||
- uses: actions/checkout@v2
|
||||
- run: make
|
||||
- name: Setup Python
|
||||
uses: actions/setup-python@v4
|
||||
with:
|
||||
python-version: "3.10"
|
||||
cache: "pip"
|
||||
cache-dependency-path: "tools/requirements.txt"
|
||||
- name: Install tools dependencies
|
||||
run: python -m pip install -r tools/requirements.txt
|
||||
- name: Test Tools
|
||||
run: make -f tools/Makefile test_tools
|
||||
- name: Verify Specification
|
||||
run: make -f tools/Makefile verify
|
||||
|
|
|
@ -3,3 +3,4 @@ gen/
|
|||
.vscode/
|
||||
gen/
|
||||
.DS_Store
|
||||
*.pyc
|
26
Makefile
26
Makefile
|
@ -1,26 +0,0 @@
|
|||
all: verify
|
||||
|
||||
verify:
|
||||
@echo Running href checker:
|
||||
@# Use "-x" if you want to skip external links
|
||||
@tools/verify-links.sh -t -v .
|
||||
@echo Running the spec phrase checker:
|
||||
@tools/verify-specs.sh -v \
|
||||
amqp-protocol-binding.md \
|
||||
avro-format.md \
|
||||
documented-extensions.md \
|
||||
http-protocol-binding.md \
|
||||
http-webhook.md \
|
||||
json-format.md \
|
||||
kafka-protocol-binding.md \
|
||||
mqtt-protocol-binding.md \
|
||||
nats-protocol-binding.md \
|
||||
protobuf-format.md \
|
||||
spec.md \
|
||||
websockets-protocol-binding.md \
|
||||
\
|
||||
discovery.md \
|
||||
pagination.md \
|
||||
subscriptions-api.md
|
||||
@echo Running the doc phrase checker:
|
||||
@tools/verify-docs.sh -v .
|
5
OWNERS
5
OWNERS
|
@ -1,9 +1,10 @@
|
|||
# See the GOVERNANCE.md document for the definition of the roles and
|
||||
# See the docs/GOVERNANCE.md document for the definition of the roles and
|
||||
# responsibilities
|
||||
admins:
|
||||
- deissnerk
|
||||
- duglin
|
||||
- markpeek
|
||||
- kenowens12
|
||||
- markpeek
|
||||
approvers:
|
||||
# Approvers are "Voting Members" as defined in the GOVERNANCE.md document.
|
||||
# See the "Voting Rights?" column in:
|
||||
|
|
132
README.md
132
README.md
|
@ -1,6 +1,11 @@
|
|||
# CloudEvents
|
||||
|
||||

|
||||
<!-- no verify-specs -->
|
||||
|
||||

|
||||
|
||||
[](https://clomonitor.io/projects/cncf/cloudevents)
|
||||
[](https://bestpractices.coreinfrastructure.org/projects/6770)
|
||||
|
||||
Events are everywhere. However, event producers tend to describe events
|
||||
differently.
|
||||
|
@ -18,86 +23,118 @@ CloudEvents has received a large amount of industry interest, ranging from major
|
|||
cloud providers to popular SaaS companies. CloudEvents is hosted by the
|
||||
[Cloud Native Computing Foundation](https://cncf.io) (CNCF) and was approved as
|
||||
a Cloud Native sandbox level project on
|
||||
[May 15, 2018](https://docs.google.com/presentation/d/1KNSv70fyTfSqUerCnccV7eEC_ynhLsm9A_kjnlmU_t0/edit#slide=id.g37acf52904_1_41).
|
||||
[May 15, 2018](https://docs.google.com/presentation/d/1KNSv70fyTfSqUerCnccV7eEC_ynhLsm9A_kjnlmU_t0/edit#slide=id.g37acf52904_1_41), an
|
||||
incubator project on [Oct 24, 2019](https://github.com/cncf/toc/pull/297)
|
||||
and a graduated project on [Jan 25, 2024](https://github.com/cncf/toc/pull/996)
|
||||
([announcement](https://www.cncf.io/announcements/2024/01/25/cloud-native-computing-foundation-announces-the-graduation-of-cloudevents/)).
|
||||
|
||||
## CloudEvents Documents
|
||||
|
||||
The following documents are available:
|
||||
|
||||
| | Latest Release | Working Draft |
|
||||
| :---------------------------- | :-----------------------------------------------------------------------------: | :--------------------------------------------------------------------------------------: |
|
||||
| **Core Specification:** |
|
||||
| CloudEvents | [v1.0.1](https://github.com/cloudevents/spec/blob/v1.0.1/spec.md) | [master](https://github.com/cloudevents/spec/blob/master/spec.md) |
|
||||
| CloudEvents | [v1.0.2](https://github.com/cloudevents/spec/blob/v1.0.2/cloudevents/spec.md) | [WIP](cloudevents/spec.md) |
|
||||
| |
|
||||
| **Optional Specifications:** |
|
||||
| AMQP Protocol Binding | [v1.0.1](https://github.com/cloudevents/spec/blob/v1.0.1/amqp-protocol-binding.md) | [master](https://github.com/cloudevents/spec/blob/master/amqp-protocol-binding.md) |
|
||||
| AVRO Event Format | [v1.0.1](https://github.com/cloudevents/spec/blob/v1.0.1/avro-format.md) | [master](https://github.com/cloudevents/spec/blob/master/avro-format.md) |
|
||||
| HTTP Protocol Binding | [v1.0.1](https://github.com/cloudevents/spec/blob/v1.0.1/http-protocol-binding.md) | [master](https://github.com/cloudevents/spec/blob/master/http-protocol-binding.md) |
|
||||
| JSON Event Format | [v1.0.1](https://github.com/cloudevents/spec/blob/v1.0.1/json-format.md) | [master](https://github.com/cloudevents/spec/blob/master/json-format.md) |
|
||||
| Kafka Protocol Binding | [v1.0.1](https://github.com/cloudevents/spec/blob/v1.0.1/kafka-protocol-binding.md) | [master](https://github.com/cloudevents/spec/blob/master/kafka-protocol-binding.md) |
|
||||
| MQTT Protocol Binding | [v1.0.1](https://github.com/cloudevents/spec/blob/v1.0.1/mqtt-protocol-binding.md) | [master](https://github.com/cloudevents/spec/blob/master/mqtt-protocol-binding.md) |
|
||||
| NATS Protocol Binding | [v1.0.1](https://github.com/cloudevents/spec/blob/v1.0.1/nats-protocol-binding.md) | [master](https://github.com/cloudevents/spec/blob/master/nats-protocol-binding.md) |
|
||||
| WebSockets Protocol Binding | - | [master](https://github.com/cloudevents/spec/blob/master/websockets-protocol-binding.md) |
|
||||
| Protobuf Event Format | | [v1.0-rc1](https://github.com/cloudevents/spec/blob/master/protobuf-format.md) |
|
||||
| Web hook | [v1.0.1](https://github.com/cloudevents/spec/blob/v1.0.1/http-webhook.md) | [master](https://github.com/cloudevents/spec/blob/master/http-webhook.md) |
|
||||
| AMQP Protocol Binding | [v1.0.2](https://github.com/cloudevents/spec/blob/v1.0.2/cloudevents/bindings/amqp-protocol-binding.md) | [WIP](cloudevents/bindings/amqp-protocol-binding.md) |
|
||||
| AVRO Event Format | [v1.0.2](https://github.com/cloudevents/spec/blob/v1.0.2/cloudevents/formats/avro-format.md) | [WIP](cloudevents/formats/avro-format.md) |
|
||||
| AVRO Compact Event Format | | [WIP](cloudevents/working-drafts/avro-compact-format.md) |
|
||||
| HTTP Protocol Binding | [v1.0.2](https://github.com/cloudevents/spec/blob/v1.0.2/cloudevents/bindings/http-protocol-binding.md) | [WIP](cloudevents/bindings/http-protocol-binding.md) |
|
||||
| JSON Event Format | [v1.0.2](https://github.com/cloudevents/spec/blob/v1.0.2/cloudevents/formats/json-format.md) | [WIP](cloudevents/formats/json-format.md) |
|
||||
| Kafka Protocol Binding | [v1.0.2](https://github.com/cloudevents/spec/blob/v1.0.2/cloudevents/bindings/kafka-protocol-binding.md) | [WIP](cloudevents/bindings/kafka-protocol-binding.md) |
|
||||
| MQTT Protocol Binding | [v1.0.2](https://github.com/cloudevents/spec/blob/v1.0.2/cloudevents/bindings/mqtt-protocol-binding.md) | [WIP](cloudevents/bindings/mqtt-protocol-binding.md) |
|
||||
| NATS Protocol Binding | [v1.0.2](https://github.com/cloudevents/spec/blob/v1.0.2/cloudevents/bindings/nats-protocol-binding.md) | [WIP](cloudevents/bindings/nats-protocol-binding.md) |
|
||||
| WebSockets Protocol Binding | - | [WIP](cloudevents/bindings/websockets-protocol-binding.md) |
|
||||
| Protobuf Event Format | [v1.0.2](https://github.com/cloudevents/spec/blob/v1.0.2/cloudevents/formats/protobuf-format.md) | [WIP](cloudevents/formats/protobuf-format.md) |
|
||||
| XML Event Format | - | [WIP](cloudevents/working-drafts/xml-format.md) |
|
||||
| Web hook | [v1.0.2](https://github.com/cloudevents/spec/blob/v1.0.2/cloudevents/http-webhook.md) | [WIP](cloudevents/http-webhook.md) |
|
||||
| |
|
||||
| **Additional Documentation:** |
|
||||
| CloudEvents Adapters | - | [master](https://github.com/cloudevents/spec/blob/master/adapters.md) |
|
||||
| CloudEvents SDK Requirements | - | [master](https://github.com/cloudevents/spec/blob/master/SDK.md) |
|
||||
| Documented Extensions | - | [master](https://github.com/cloudevents/spec/blob/master/documented-extensions.md) |
|
||||
| Primer | [v1.0.1](https://github.com/cloudevents/spec/blob/v1.0.1/primer.md) | [master](https://github.com/cloudevents/spec/blob/master/primer.md) |
|
||||
| Proprietary Specifications | - | [master](https://github.com/cloudevents/spec/blob/master/proprietary-specs.md) |
|
||||
| CloudEvents Primer | [v1.0.2](https://github.com/cloudevents/spec/blob/v1.0.2/cloudevents/primer.md) | [WIP](cloudevents/primer.md) |
|
||||
| [CloudEvents Adapters](cloudevents/adapters/README.md) | - | [Not versioned](cloudevents/adapters/README.md) |
|
||||
| [CloudEvents SDK Requirements](cloudevents/SDK.md) | - | [Not versioned](cloudevents/SDK.md) |
|
||||
| [Documented Extensions](cloudevents/extensions/README.md) | - | [Not versioned](cloudevents/extensions/README.md) |
|
||||
| [Proprietary Specifications](cloudevents/proprietary-specs.md) | - | [Not versioned](cloudevents/proprietary-specs.md) |
|
||||
|
||||
## Other Specifications
|
||||
| | Latest Release | Working Draft |
|
||||
| :-------------- | :-------------------------------------------------------------: | :---------------------------: |
|
||||
| CE SQL | [v1.0.0](https://github.com/cloudevents/spec/tree/cesql/v1.0.0/cesql) | [WIP](cesql/spec.md) |
|
||||
| Subscriptions | - | [WIP](subscriptions/spec.md) |
|
||||
|
||||
The Registry and Pagination specifications can now be found in the
|
||||
[xRegistry/spec](https://github.com/xregistry/spec) repo.
|
||||
|
||||
Additional release related information:
|
||||
[Historical releases and changelogs](docs/RELEASES.md)
|
||||
|
||||
If you are new to CloudEvents, it is recommended that you start by reading the
|
||||
[Primer](primer.md) for an overview of the specification's goals and design
|
||||
decisions, and then move on to the [core specification](spec.md).
|
||||
[Primer](cloudevents/primer.md) for an overview of the specification's goals
|
||||
and design decisions, and then move on to the
|
||||
[core specification](cloudevents/spec.md).
|
||||
|
||||
Since not all event producers generate CloudEvents by default, there is
|
||||
documentation describing the recommended process for adapting some popular
|
||||
events into CloudEvents, see
|
||||
[CloudEvents Adapters](https://github.com/cloudevents/spec/blob/master/adapters.md).
|
||||
[CloudEvents Adapters](cloudevents/adapters/README.md).
|
||||
|
||||
## SDKs
|
||||
|
||||
In addition to the documentation mentioned above, there is also an
|
||||
[SDK proposal](SDK.md). A set of SDKs is also being developed:
|
||||
In addition to the documentation mentioned above, there are also a set of
|
||||
language specific SDKs being developed:
|
||||
|
||||
- [CSharp](https://github.com/cloudevents/sdk-csharp)
|
||||
- [C#/.NET](https://github.com/cloudevents/sdk-csharp)
|
||||
- [Go](https://github.com/cloudevents/sdk-go)
|
||||
- [Java](https://github.com/cloudevents/sdk-java)
|
||||
- [Javascript](https://github.com/cloudevents/sdk-javascript)
|
||||
- [PHP](https://github.com/cloudevents/sdk-php)
|
||||
- [PowerShell](https://github.com/cloudevents/sdk-powershell)
|
||||
- [Python](https://github.com/cloudevents/sdk-python)
|
||||
- [Ruby](https://github.com/cloudevents/sdk-ruby)
|
||||
- [Rust](https://github.com/cloudevents/sdk-rust)
|
||||
|
||||
## Community
|
||||
The [SDK requirements](cloudevents/SDK.md) document provides information
|
||||
on how the SDKs are managed and what is expected of each one.
|
||||
The SDK [feature support table](cloudevents/SDK.md#feature-support) is a
|
||||
good resource to see which features, event formats and bindings are supported
|
||||
by each SDK.
|
||||
|
||||
For more information about how the SDKs operate, please see the following
|
||||
documents:
|
||||
- [SDK Governance](docs/SDK-GOVERNANCE.md)
|
||||
- [SDK Maintainer Guidlines](docs/SDK-maintainer-guidelines.md)
|
||||
- [SDK PR Guidlines](docs/SDK-PR-guidelines.md)
|
||||
|
||||
## Community and Docs
|
||||
|
||||
Learn more about the people and organizations who are creating a dynamic cloud
|
||||
native ecosystem by making our systems interoperable with CloudEvents.
|
||||
|
||||
- Our [Governance](community/GOVERNANCE.md) documentation.
|
||||
- How to [contribute](community/CONTRIBUTING.md) via issues and pull requests.
|
||||
- [Contributors](community/contributors.md): people and organizations who helped
|
||||
- Our [Governance](docs/GOVERNANCE.md) documentation.
|
||||
- [Contributing](docs/CONTRIBUTING.md) guidance.
|
||||
- [Roadmap](docs/ROADMAP.md)
|
||||
- [Adopters](https://cloudevents.io/) - See "Integrations".
|
||||
- [Contributors](docs/contributors.md): people and organizations who helped
|
||||
us get started or are actively working on the CloudEvents specification.
|
||||
- [Demos & open source](community/README.md) -- if you have something to share
|
||||
- [Presentations, notes and other misc shared
|
||||
docs](https://drive.google.com/drive/folders/1eKH-tVNV25jwkuBEoi3ESqvVjNRlJqYX?usp=sharing)
|
||||
- [Demos & open source](docs/README.md) -- if you have something to share
|
||||
about your use of CloudEvents, please submit a PR!
|
||||
- [Potential CloudEvents v2 work items](cloudevents/v2.md)
|
||||
- [Code of Conduct](https://github.com/cncf/foundation/blob/master/code-of-conduct.md)
|
||||
|
||||
## Process
|
||||
### Security Concerns
|
||||
|
||||
The CloudEvents project is working to formalize the [specification](spec.md)
|
||||
based on [design goals](primer.md#design-goals) which focus on interoperability
|
||||
between systems which generate and respond to events.
|
||||
If there is a security concern with one of the CloudEvents specifications, or
|
||||
with one of the project's SDKs, please send an email to
|
||||
[cncf-cloudevents-security@lists.cncf.io](mailto:cncf-cloudevents-security@lists.cncf.io).
|
||||
|
||||
In order to achieve these goals, the project must describe:
|
||||
A security assessment was performed by
|
||||
[Trail of Bits](https://www.trailofbits.com/) in October 2022. The report
|
||||
can be found [here](docs/CE-SecurityAudit-2022-10.pdf) or on the Trail of Bits
|
||||
[website](https://github.com/trailofbits/publications/blob/master/reviews/CloudEvents.pdf).
|
||||
|
||||
- Common attributes of an _event_ that facilitate interoperability
|
||||
- One or more common architectures that are in active use today or planned to be
|
||||
built by its members
|
||||
- How events are transported from producer to consumer via at least one protocol
|
||||
- Identify and resolve whatever else is needed for interoperability
|
||||
|
||||
## Communications
|
||||
### Communications
|
||||
|
||||
The main mailing list for e-mail communications:
|
||||
|
||||
|
@ -115,7 +152,10 @@ For SDK related comments and questions:
|
|||
- Archives are at: https://lists.cncf.io/g/cncf-cloudevents-sdk/topics
|
||||
- Slack: #cloudeventssdk on [CNCF's Slack workspace](http://slack.cncf.io/)
|
||||
|
||||
## Meeting Time
|
||||
For SDK specific communications, please see the main README in each
|
||||
SDK's github repo - see the [list of SDKs](#sdks).
|
||||
|
||||
### Meeting Time
|
||||
|
||||
See the [CNCF public events calendar](https://www.cncf.io/community/calendar/).
|
||||
This specification is being developed by the
|
||||
|
@ -127,7 +167,9 @@ Please see the
|
|||
[meeting minutes doc](https://docs.google.com/document/d/1OVF68rpuPK5shIHILK9JOqlZBbfe91RNzQ7u_P7YCDE/edit#)
|
||||
for the latest information on how to join the calls.
|
||||
|
||||
Recording from our calls are available
|
||||
Recording from our calls are available
|
||||
[here](https://www.youtube.com/playlist?list=PLO-qzjSpLN1BEyKjOVX_nMg7ziHXUYwec), and
|
||||
older ones are
|
||||
[here](https://www.youtube.com/playlist?list=PLj6h78yzYM2Ph7YoBIgsZNW_RGJvNlFOt).
|
||||
|
||||
Periodically, the group may have in-person meetings that coincide with a major
|
||||
|
|
137
SDK.md
137
SDK.md
|
@ -1,137 +0,0 @@
|
|||
# CloudEvents SDK Requirements
|
||||
|
||||
The intent of this document to describe a minimum set of requirements for new
|
||||
Software Development Kits (SDKs) for CloudEvents. These SDKs are designed and
|
||||
implemented to enhance and speed up CloudEvents integration. As part of
|
||||
community efforts CloudEvents team committed to support and maintain the
|
||||
following SDKs:
|
||||
|
||||
- [CSharp](https://github.com/cloudevents/sdk-csharp)
|
||||
- [Go SDK](https://github.com/cloudevents/sdk-go)
|
||||
- [Java SDK](https://github.com/cloudevents/sdk-java)
|
||||
- [JavaScript SDK](https://github.com/cloudevents/sdk-javascript)
|
||||
- [PHP SDK](https://github.com/cloudevents/sdk-php)
|
||||
- [Python SDK](https://github.com/cloudevents/sdk-python)
|
||||
- [Ruby SDK](https://github.com/cloudevents/sdk-ruby)
|
||||
- [Rust SDK](https://github.com/cloudevents/sdk-rust)
|
||||
|
||||
This is intended to provide guidance and requirements for SDK authors. This
|
||||
document is intended to be kept up to date with the CloudEvents spec.
|
||||
|
||||
## Contribution Acceptance
|
||||
|
||||
Being an open source community the CloudEvents team is open for new members as
|
||||
well open to their contributions. In order to ensure that an SDK is going to be
|
||||
supported and maintained the CloudEvents community would like to ensure that:
|
||||
|
||||
- Each SDK has active points of contact.
|
||||
- Each SDK supports the latest(N), and N-1, major releases of the
|
||||
[CloudEvent spec](spec.md)\*.
|
||||
- Within the scope of a major release, only support for the latest minor
|
||||
version is needed.
|
||||
|
||||
Support for release candidates is not required, but strongly encouraged.
|
||||
|
||||
\* Note: v1.0 is a special case and it is recommended that as long as v1.0
|
||||
is the latest version, SDKs should also support v0.3.
|
||||
|
||||
## Technical Requirements
|
||||
|
||||
Each SDK MUST meet these requirements:
|
||||
|
||||
- Supports CloudEvents at spec milestones and ongoing development version.
|
||||
- Encode a canonical Event into a transport specific encoded message.
|
||||
- Decode transport specific encoded messages into a Canonical Event.
|
||||
- Idiomatic usage of the programming language.
|
||||
- Using current language version(s).
|
||||
- Supports HTTP transport renderings in both `structured` and `binary`
|
||||
encodings.
|
||||
|
||||
### Object Model Structure Guidelines
|
||||
|
||||
Each SDK will provide a generic CloudEvents class/object/structure that
|
||||
represents the canonical form of an Event.
|
||||
|
||||
The SDK should enable users to bypass implementing transport specific encoding
|
||||
and decoding of the CloudEvents `Event` object. The general flow for Objects
|
||||
should be:
|
||||
|
||||
```
|
||||
Event (-> Message) -> Transport
|
||||
```
|
||||
|
||||
and
|
||||
|
||||
```
|
||||
Transport (-> Message) -> Event
|
||||
```
|
||||
|
||||
An SDK is not required to implement a wrapper around the transport, the focus
|
||||
should be around allowing programming models to work with the high level `Event`
|
||||
object, and providing tools to take the `Event` and turn it into something that
|
||||
can be used with the implementation transport selected.
|
||||
|
||||
At a high level, the SDK needs to be able to help with the following tasks:
|
||||
|
||||
1. Compose an Event.
|
||||
1. Encode an Event given a transport and encoding (into a Transport Message if
|
||||
appropriate).
|
||||
1. Decode an Event given a transport specific message, request or response (into
|
||||
a Transport Message if appropriate).
|
||||
|
||||
#### Compose an Event
|
||||
|
||||
Provide a convenient way to compose both a single message and many messages.
|
||||
Implementers will need a way to quickly build up and convert their event data
|
||||
into the a CloudEvents encoded Event. In practice there tend to be two aspects
|
||||
to event composition,
|
||||
|
||||
1. Event Creation
|
||||
|
||||
- "I have this data that is not formatted as a CloudEvent and I want it to be."
|
||||
|
||||
1. Event Mutation
|
||||
|
||||
- "I have a CloudEvents formatted Event and I need it to be a different Event."
|
||||
- "I have a CloudEvents formatted Event and I need to mutate the Event."
|
||||
|
||||
Event creation is highly idiomatic to the SDK language.
|
||||
|
||||
Event mutation tends to be solved with an accessor pattern, like getters and
|
||||
setters. But direct key access could be leveraged, or named-key accessor
|
||||
functions.
|
||||
|
||||
In either case, there MUST be a method for validating the resulting Event object
|
||||
based on the parameters set, most importantly the CloudEvents spec version.
|
||||
|
||||
#### Encode/Decode an Event
|
||||
|
||||
Each SDK will support encoding and decoding an Event with regards to a transport
|
||||
and encoding. `Structured` encoding is the easiest to support, as it is just
|
||||
`json`, but `Binary` is fairly custom for each transport.
|
||||
|
||||
#### Data
|
||||
|
||||
Data access from the event has some considerations, the Event at rest could be
|
||||
encoded into the `base64` form, as structured data, or as a wire format like
|
||||
`json`. An SDK MUST provide a method for unpacking the data from these formats
|
||||
into a native format.
|
||||
|
||||
#### Extensions
|
||||
|
||||
Supporting CloudEvents extensions is idiomatic again, but a method that mirrors
|
||||
the data access seems to work.
|
||||
|
||||
#### Validation
|
||||
|
||||
Validation MUST be possible on an individual Event. Validation MUST take into
|
||||
account the spec version, and all the requirements put in-place by the spec at
|
||||
each version.
|
||||
|
||||
## Documentation
|
||||
|
||||
Each SDK must provide examples using at least HTTP transport of:
|
||||
|
||||
- Composing an Event.
|
||||
- Encoding and sending a composed Event.
|
||||
- Receiving and decoding an Event.
|
|
@ -1,130 +0,0 @@
|
|||
openapi: '3.0.2'
|
||||
info:
|
||||
title: CloudEvents discovery API
|
||||
description: CloudEvents discovery API specification according to [Discovery - Version 0.1-wip](https://github.com/cloudevents/spec/blob/master/discovery.md#service).
|
||||
version: '0.1-WIP'
|
||||
servers:
|
||||
- url: https://api.cloudevents.io/test/v0.1
|
||||
paths:
|
||||
/services:
|
||||
get:
|
||||
parameters:
|
||||
- in: query
|
||||
name: matching
|
||||
description: The search term.
|
||||
required: false
|
||||
schema:
|
||||
type: string
|
||||
responses:
|
||||
'200':
|
||||
description: A list of services (optionally matching the query parameter).
|
||||
content:
|
||||
application/json:
|
||||
schema:
|
||||
type: array
|
||||
items:
|
||||
$ref: '#/components/schemas/service'
|
||||
/services/{name}:
|
||||
get:
|
||||
parameters:
|
||||
- in: path
|
||||
name: name
|
||||
description: The name of the service to be returned.
|
||||
required: true
|
||||
schema:
|
||||
type: string
|
||||
responses:
|
||||
'200':
|
||||
description: The corresponding service.
|
||||
content:
|
||||
application/json:
|
||||
schema:
|
||||
type: array
|
||||
items:
|
||||
$ref: '#/components/schemas/service'
|
||||
components:
|
||||
schemas:
|
||||
service:
|
||||
type: object
|
||||
properties:
|
||||
name:
|
||||
type: string
|
||||
description: A unique identifier for this Service. This value MUST be unique within the scope of this Discovery Endpoint.
|
||||
example: storage, github
|
||||
url:
|
||||
type: string
|
||||
description: A URL that references this Service. This value MUST be usable in subsequent requests, by authorized clients, to retrieve this Service entity.
|
||||
example: http://example.com/services/storage, http://discovery.github.com/services/github
|
||||
description:
|
||||
type: string
|
||||
description: Human readable description.
|
||||
docsurl:
|
||||
type: string
|
||||
description: Absolute URL that provides a link to additional documentation about the service. This is intended for a developer to use in order to learn more about this service's events produced.
|
||||
example: http://cloud.example.com/docs/blobstorage
|
||||
specversions:
|
||||
type: object
|
||||
description: CloudEvents specversions that can be used for events published for this service.
|
||||
subscriptionurl:
|
||||
type: string
|
||||
description: An absolute URL indicating where CloudSubscriptions subscribe API calls MUST be sent to.
|
||||
subscriptionconfig:
|
||||
type: object
|
||||
description: "A map indicating supported options for the config parameter for the CloudSubscriptions subscribe() API call. Keys are the name of keys in the allowed config map, the values indicate the type of that parameter, confirming to the CloudEvents type system. TODO: Needs resolution with CloudSubscriptions API"
|
||||
additionalProperties:
|
||||
type: string
|
||||
authscope:
|
||||
type: string
|
||||
description: Authorization scope needed for creating subscriptions. The actual meaning of this field is determined on a per-service basis.
|
||||
example: storage.read
|
||||
protocols:
|
||||
type: array
|
||||
description: This field describes the different values that might be passed in the protocol field of the CloudSubscriptions API. The protocols with existing CloudEvents bindings are identified as AMQP, MQTT3, MQTT5, HTTP, KAFKA, and NATS. An implementation MAY add support for further protocols. All services MUST support at least one delivery protocol, and MAY support additional protocols.
|
||||
items:
|
||||
type: string
|
||||
description: protocol
|
||||
example: '[ "HTTP", "AMQP", "KAFKA" ]'
|
||||
events:
|
||||
type: array
|
||||
description: List of event types available in this service.
|
||||
items:
|
||||
$ref: '#/components/schemas/type'
|
||||
type:
|
||||
type: object
|
||||
properties:
|
||||
type:
|
||||
type: string
|
||||
description: CloudEvents type attribute.
|
||||
example: com.github.pull.create, com.example.object.delete.v2
|
||||
description:
|
||||
type: string
|
||||
description: Human readable description.
|
||||
dataschema:
|
||||
type: string
|
||||
description: CloudEvents datacontenttype attribute. Indicating how the data attribute of subscribed events will be encoded.
|
||||
dataschematype:
|
||||
type: string
|
||||
description: If using dataschemacontent for inline schema storage, the dataschematype indicates the type of schema represented there.
|
||||
dataschemacontent:
|
||||
type: string
|
||||
description: An inline representation of the schema of the data attribute encoding mechanism. This is an alternative to using the dataschema attribute.
|
||||
sourcetemplate:
|
||||
type: string
|
||||
description: A URI Template according to RFC 6570 that defines how the source attribute will be generated.
|
||||
example: "http://blob.store/{bucket}"
|
||||
extensions:
|
||||
type: array
|
||||
description: An array or CloudEvents Extension Context Attributes that are used for this event type.
|
||||
items:
|
||||
type: object
|
||||
properties:
|
||||
name:
|
||||
type: string
|
||||
description: The CloudEvents context attribute name used by this extension.
|
||||
type:
|
||||
type: string
|
||||
description: The data type of the extension attribute.
|
||||
specurl:
|
||||
type: string
|
||||
description: An attribute pointing to the specification that defines the extension.
|
||||
example: '{ "name": "dataref", "type": "URI-reference", "specurl": "https://github.com/cloudevents/spec/blob/master/extensions/dataref.md" }'
|
|
@ -0,0 +1,79 @@
|
|||
lexer grammar CESQLLexer;
|
||||
|
||||
// NOTE:
|
||||
// This grammar is case-sensitive, although CESQL keywords are case-insensitive.
|
||||
// In order to implement case-insensitivity, check out
|
||||
// https://github.com/antlr/antlr4/blob/master/doc/case-insensitive-lexing.md#custom-character-streams-approach
|
||||
|
||||
// Skip tab, carriage return and newlines
|
||||
|
||||
SPACE: [ \t\r\n]+ -> skip;
|
||||
|
||||
// Fragments for Literal primitives
|
||||
|
||||
fragment ID_LITERAL: [a-zA-Z0-9]+;
|
||||
fragment DQUOTA_STRING: '"' ( '\\'. | '""' | ~('"'| '\\') )* '"';
|
||||
fragment SQUOTA_STRING: '\'' ('\\'. | '\'\'' | ~('\'' | '\\'))* '\'';
|
||||
fragment INT_DIGIT: [0-9];
|
||||
fragment FN_LITERAL: [A-Z] [A-Z_]*;
|
||||
|
||||
// Constructors symbols
|
||||
|
||||
LR_BRACKET: '(';
|
||||
RR_BRACKET: ')';
|
||||
COMMA: ',';
|
||||
SINGLE_QUOTE_SYMB: '\'';
|
||||
DOUBLE_QUOTE_SYMB: '"';
|
||||
|
||||
fragment QUOTE_SYMB
|
||||
: SINGLE_QUOTE_SYMB | DOUBLE_QUOTE_SYMB
|
||||
;
|
||||
|
||||
// Operators
|
||||
// - Logic
|
||||
|
||||
AND: 'AND';
|
||||
OR: 'OR';
|
||||
XOR: 'XOR';
|
||||
NOT: 'NOT';
|
||||
|
||||
// - Arithmetics
|
||||
|
||||
STAR: '*';
|
||||
DIVIDE: '/';
|
||||
MODULE: '%';
|
||||
PLUS: '+';
|
||||
MINUS: '-';
|
||||
|
||||
// - Comparison
|
||||
|
||||
EQUAL: '=';
|
||||
NOT_EQUAL: '!=';
|
||||
GREATER: '>';
|
||||
GREATER_OR_EQUAL: '>=';
|
||||
LESS: '<';
|
||||
LESS_GREATER: '<>';
|
||||
LESS_OR_EQUAL: '<=';
|
||||
|
||||
// Like, exists, in
|
||||
|
||||
LIKE: 'LIKE';
|
||||
EXISTS: 'EXISTS';
|
||||
IN: 'IN';
|
||||
|
||||
// Booleans
|
||||
|
||||
TRUE: 'TRUE';
|
||||
FALSE: 'FALSE';
|
||||
|
||||
// Literals
|
||||
|
||||
DQUOTED_STRING_LITERAL: DQUOTA_STRING;
|
||||
SQUOTED_STRING_LITERAL: SQUOTA_STRING;
|
||||
INTEGER_LITERAL: ( '+' | '-' )? INT_DIGIT+;
|
||||
|
||||
// Identifiers
|
||||
|
||||
IDENTIFIER: [a-zA-Z]+;
|
||||
IDENTIFIER_WITH_NUMBER: [a-zA-Z0-9]+;
|
||||
FUNCTION_IDENTIFIER_WITH_UNDERSCORE: [A-Z] [A-Z_]*;
|
|
@ -0,0 +1,62 @@
|
|||
grammar CESQLParser;
|
||||
|
||||
import CESQLLexer;
|
||||
|
||||
// Entrypoint
|
||||
cesql: expression EOF;
|
||||
|
||||
// Structure of operations, function invocations and expression
|
||||
expression
|
||||
: functionIdentifier functionParameterList #functionInvocationExpression
|
||||
// unary operators are the highest priority
|
||||
| NOT expression #unaryLogicExpression
|
||||
| MINUS expression # unaryNumericExpression
|
||||
// LIKE, EXISTS and IN takes precedence over all the other binary operators
|
||||
| expression NOT? LIKE stringLiteral #likeExpression
|
||||
| EXISTS identifier #existsExpression
|
||||
| expression NOT? IN setExpression #inExpression
|
||||
// Numeric operations
|
||||
| expression (STAR | DIVIDE | MODULE) expression #binaryMultiplicativeExpression
|
||||
| expression (PLUS | MINUS) expression #binaryAdditiveExpression
|
||||
// Comparison operations
|
||||
| expression (EQUAL | NOT_EQUAL | LESS_GREATER | GREATER_OR_EQUAL | LESS_OR_EQUAL | LESS | GREATER) expression #binaryComparisonExpression
|
||||
// Logic operations
|
||||
|<assoc=right> expression (AND | OR | XOR) expression #binaryLogicExpression
|
||||
// Subexpressions and atoms
|
||||
| LR_BRACKET expression RR_BRACKET #subExpression
|
||||
| atom #atomExpression
|
||||
;
|
||||
|
||||
atom
|
||||
: booleanLiteral #booleanAtom
|
||||
| integerLiteral #integerAtom
|
||||
| stringLiteral #stringAtom
|
||||
| identifier #identifierAtom
|
||||
;
|
||||
|
||||
// Identifiers
|
||||
|
||||
identifier
|
||||
: (IDENTIFIER | IDENTIFIER_WITH_NUMBER)
|
||||
;
|
||||
functionIdentifier
|
||||
: (IDENTIFIER | FUNCTION_IDENTIFIER_WITH_UNDERSCORE)
|
||||
;
|
||||
|
||||
// Literals
|
||||
|
||||
booleanLiteral: (TRUE | FALSE);
|
||||
stringLiteral: (DQUOTED_STRING_LITERAL | SQUOTED_STRING_LITERAL);
|
||||
integerLiteral: INTEGER_LITERAL;
|
||||
|
||||
// Functions
|
||||
|
||||
functionParameterList
|
||||
: LR_BRACKET ( expression ( COMMA expression )* )? RR_BRACKET
|
||||
;
|
||||
|
||||
// Sets
|
||||
|
||||
setExpression
|
||||
: LR_BRACKET expression ( COMMA expression )* RR_BRACKET // Empty sets are not allowed
|
||||
;
|
|
@ -0,0 +1,7 @@
|
|||
# CloudEvents SQL Expression Language - Version 1.0.0
|
||||
|
||||
CloudEvents SQL expressions (also known as CESQL) allow computing values and
|
||||
matching of CloudEvent attributes against complex expressions that lean on the
|
||||
syntax of Structured Query Language (SQL) `WHERE` clauses.
|
||||
|
||||
For more information, see the [CESQL specification](spec.md).
|
|
@ -0,0 +1,25 @@
|
|||
# CESQL Release Notes
|
||||
|
||||
<!-- no verify-specs -->
|
||||
|
||||
## v1.0.0 - 2024/06/13
|
||||
This is the v1 release of the specification! CESQL v1 provides users with the
|
||||
ability to write and execute queries against CloudEvents. This allows for
|
||||
computing values and matchins of CloudEvent attributes against complex
|
||||
expressions that lean on the syntax of Structured Query Language (SQL).
|
||||
|
||||
Notable changes between the WIP draft and the v1 specification are:
|
||||
- Specify error types
|
||||
- Clarify return values of expressions that encounter errors
|
||||
- Clarify that missing attributes result in an error and the expression
|
||||
returning it's default value
|
||||
- Add support for boolean to integer and integer to boolean type casting
|
||||
- Clarify the order of operations
|
||||
- Clarify how user defined functions work
|
||||
- Define the default "zero" values for the built in types
|
||||
- Clarify that string comparisons are case sensitive
|
||||
- Specify which characters are treated as whitespace for the TRIM function
|
||||
- Specify that functions must still return values along with errors, as well as
|
||||
the behaviour when user defined function do not do this correctly
|
||||
- For the fail fast error handling mode, expressions now return the zero value
|
||||
for their return type when they encounter an error, rather than undefined
|
|
@ -0,0 +1,29 @@
|
|||
# CloudEvents Expression Language TCK
|
||||
|
||||
Each file of this TCK contains a set of test cases, testing one or more specific features of the language.
|
||||
|
||||
The root file structure is composed by:
|
||||
|
||||
* `name`: Name of the test suite contained in the file
|
||||
* `tests`: List of tests
|
||||
|
||||
Each test definition includes:
|
||||
|
||||
* `name`: Name of the test case
|
||||
* `expression`: Expression to test.
|
||||
* `result`: Expected result (OPTIONAL). Can be a boolean, an integer or a string.
|
||||
* `error`: Expected error (OPTIONAL). If absent, no error is expected.
|
||||
* `event`: Input event (OPTIONAL). If present, this is a valid event serialized in JSON format. If absent, when testing
|
||||
the expression, any valid event can be passed.
|
||||
* `eventOverrides`: Overrides to the input event (OPTIONAL). This might be used when `event` is missing, in order to
|
||||
define only some specific values, while the other (REQUIRED) attributes can be any value.
|
||||
|
||||
The `error` values could be any of the following:
|
||||
|
||||
* `parse`: Error while parsing the expression
|
||||
* `math`: Math error while evaluating a math operator
|
||||
* `cast`: Casting error
|
||||
* `missingFunction`: Addressed a missing function
|
||||
* `functionEvaluation`: Error while evaluating a function
|
||||
* `missingAttribute`: Error due to a missing attribute
|
||||
* `generic`: A generic error
|
|
@ -0,0 +1,106 @@
|
|||
name: Binary comparison operations
|
||||
tests:
|
||||
- name: True is equal to false
|
||||
expression: TRUE = FALSE
|
||||
result: false
|
||||
- name: False is equal to false
|
||||
expression: FALSE = FALSE
|
||||
result: true
|
||||
- name: 1 is equal to 2
|
||||
expression: 1 = 2
|
||||
result: false
|
||||
- name: 2 is equal to 2
|
||||
expression: 2 = 2
|
||||
result: true
|
||||
- name: abc is equal to 123
|
||||
expression: "'abc' = '123'"
|
||||
result: false
|
||||
- name: abc is equal to abc
|
||||
expression: "'abc' = 'abc'"
|
||||
result: true
|
||||
- name: Equals operator returns false when encountering a missing attribute
|
||||
expression: missing = 2
|
||||
result: false
|
||||
error: missingAttribute
|
||||
|
||||
- name: True is not equal to false
|
||||
expression: TRUE != FALSE
|
||||
result: true
|
||||
- name: False is not equal to false
|
||||
expression: FALSE != FALSE
|
||||
result: false
|
||||
- name: 1 is not equal to 2
|
||||
expression: 1 != 2
|
||||
result: true
|
||||
- name: 2 is not equal to 2
|
||||
expression: 2 != 2
|
||||
result: false
|
||||
- name: abc is not equal to 123
|
||||
expression: "'abc' != '123'"
|
||||
result: true
|
||||
- name: abc is not equal to abc
|
||||
expression: "'abc' != 'abc'"
|
||||
result: false
|
||||
- name: Not equal operator returns false when encountering a missing attribute
|
||||
expression: missing != 2
|
||||
result: false
|
||||
error: missingAttribute
|
||||
|
||||
- name: True is not equal to false (diamond operator)
|
||||
expression: TRUE <> FALSE
|
||||
result: true
|
||||
- name: False is not equal to false (diamond operator)
|
||||
expression: FALSE <> FALSE
|
||||
result: false
|
||||
- name: 1 is not equal to 2 (diamond operator)
|
||||
expression: 1 <> 2
|
||||
result: true
|
||||
- name: 2 is not equal to 2 (diamond operator)
|
||||
expression: 2 <> 2
|
||||
result: false
|
||||
- name: abc is not equal to 123 (diamond operator)
|
||||
expression: "'abc' <> '123'"
|
||||
result: true
|
||||
- name: abc is not equal to abc (diamond operator)
|
||||
expression: "'abc' <> 'abc'"
|
||||
result: false
|
||||
- name: Diamond operator returns false when encountering a missing attribute
|
||||
expression: missing <> 2
|
||||
result: false
|
||||
error: missingAttribute
|
||||
|
||||
- name: 1 is less or equal than 2
|
||||
expression: 2 <= 2
|
||||
result: true
|
||||
- name: 3 is less or equal than 2
|
||||
expression: 3 <= 2
|
||||
result: false
|
||||
- name: 1 is less than 2
|
||||
expression: 1 < 2
|
||||
result: true
|
||||
- name: 2 is less than 2
|
||||
expression: 2 < 2
|
||||
result: false
|
||||
- name: 2 is greater or equal than 2
|
||||
expression: 2 >= 2
|
||||
result: true
|
||||
- name: 2 is greater or equal than 3
|
||||
expression: 2 >= 3
|
||||
result: false
|
||||
- name: 2 is greater than 1
|
||||
expression: 2 > 1
|
||||
result: true
|
||||
- name: 2 is greater than 2
|
||||
expression: 2 > 2
|
||||
result: false
|
||||
- name: Less than or equal operator returns false when encountering a missing attribute
|
||||
expression: missing <= 2
|
||||
result: false
|
||||
error: missingAttribute
|
||||
|
||||
- name: implicit casting with string as right type
|
||||
expression: "true = 'TRUE'"
|
||||
result: false
|
||||
- name: implicit casting with boolean as right type
|
||||
expression: "'TRUE' = true"
|
||||
result: true
|
|
@ -0,0 +1,54 @@
|
|||
name: Binary logical operations
|
||||
tests:
|
||||
- name: False and false
|
||||
expression: FALSE AND FALSE
|
||||
result: false
|
||||
- name: False and true
|
||||
expression: FALSE AND TRUE
|
||||
result: false
|
||||
- name: True and false
|
||||
expression: TRUE AND FALSE
|
||||
result: false
|
||||
- name: True and true
|
||||
expression: TRUE AND TRUE
|
||||
result: true
|
||||
- name: AND operator is short circuit evaluated
|
||||
expression: "false and (1 != 1 / 0)"
|
||||
result: false
|
||||
- name: AND operator is NOT short circuit evaluated when the first operand evaluates to true
|
||||
expression: "true and (1 != 1 / 0)"
|
||||
error: math
|
||||
result: false
|
||||
|
||||
- name: False or false
|
||||
expression: FALSE OR FALSE
|
||||
result: false
|
||||
- name: False or true
|
||||
expression: FALSE OR TRUE
|
||||
result: true
|
||||
- name: True or false
|
||||
expression: TRUE OR FALSE
|
||||
result: true
|
||||
- name: True or true
|
||||
expression: TRUE OR TRUE
|
||||
result: true
|
||||
- name: OR operator is short circuit evaluated
|
||||
expression: "true or (1 != 1 / 0)"
|
||||
result: true
|
||||
- name: OR operator is NOT short circuit evaluated when the first operand evaluates to false
|
||||
expression: "false or (1 != 1 / 0)"
|
||||
error: math
|
||||
result: false
|
||||
|
||||
- name: False xor false
|
||||
expression: FALSE XOR FALSE
|
||||
result: false
|
||||
- name: False xor true
|
||||
expression: FALSE XOR TRUE
|
||||
result: true
|
||||
- name: True xor false
|
||||
expression: TRUE XOR FALSE
|
||||
result: true
|
||||
- name: True xor true
|
||||
expression: TRUE XOR TRUE
|
||||
result: false
|
|
@ -0,0 +1,63 @@
|
|||
name: Binary math operations
|
||||
tests:
|
||||
- name: Operator precedence without parenthesis
|
||||
expression: 4 * 2 + 4 / 2
|
||||
result: 10
|
||||
- name: Operator precedence with parenthesis
|
||||
expression: 4 * (2 + 4) / 2
|
||||
result: 12
|
||||
|
||||
- name: Truncated division
|
||||
expression: 5 / 3
|
||||
result: 1
|
||||
- name: Division by zero returns 0 and fail
|
||||
expression: 5 / 0
|
||||
result: 0
|
||||
error: math
|
||||
- name: Module
|
||||
expression: 5 % 2
|
||||
result: 1
|
||||
- name: Module by zero returns 0 and fail
|
||||
expression: 5 % 0
|
||||
result: 0
|
||||
error: math
|
||||
- name: Missing attribute in division results in missing attribute error, not divide by 0 error
|
||||
expression: missing / 0
|
||||
result: 0
|
||||
error: missingAttribute
|
||||
- name: Missing attribute in modulo results in missing attribute error, not divide by 0 error
|
||||
expression: missing % 0
|
||||
result: 0
|
||||
error: missingAttribute
|
||||
|
||||
- name: Positive plus positive number
|
||||
expression: 4 + 1
|
||||
result: 5
|
||||
- name: Negative plus positive number
|
||||
expression: -4 + 1
|
||||
result: -3
|
||||
- name: Negative plus Negative number
|
||||
expression: -4 + -1
|
||||
result: -5
|
||||
- name: Positive plus negative number
|
||||
expression: 4 + -1
|
||||
result: 3
|
||||
- name: Positive minus positive number
|
||||
expression: 4 - 1
|
||||
result: 3
|
||||
- name: Negative minus positive number
|
||||
expression: -4 - 1
|
||||
result: -5
|
||||
|
||||
- name: Implicit casting, with left value string
|
||||
expression: "'5' + 3"
|
||||
result: 8
|
||||
- name: Implicit casting, with right value string
|
||||
expression: "5 + '3'"
|
||||
result: 8
|
||||
- name: Implicit casting, with both values string
|
||||
expression: "'5' + '3'"
|
||||
result: 8
|
||||
- name: Implicit casting, with boolean value
|
||||
expression: "5 + TRUE"
|
||||
result: 6
|
|
@ -0,0 +1,25 @@
|
|||
name: Case sensitivity
|
||||
tests:
|
||||
- name: TRUE
|
||||
expression: TRUE
|
||||
result: true
|
||||
- name: true
|
||||
expression: true
|
||||
result: true
|
||||
- name: tRuE
|
||||
expression: tRuE
|
||||
result: true
|
||||
|
||||
- name: FALSE
|
||||
expression: FALSE
|
||||
result: false
|
||||
- name: false
|
||||
expression: false
|
||||
result: false
|
||||
- name: FaLsE
|
||||
expression: FaLsE
|
||||
result: false
|
||||
|
||||
- name: String literals casing preserved
|
||||
expression: "'aBcD'"
|
||||
result: aBcD
|
|
@ -0,0 +1,69 @@
|
|||
name: Casting functions
|
||||
tests:
|
||||
- name: Cast '1' to integer
|
||||
expression: INT('1')
|
||||
result: 1
|
||||
- name: Cast '-1' to integer
|
||||
expression: INT('-1')
|
||||
result: -1
|
||||
- name: Cast identity 1
|
||||
expression: INT(1)
|
||||
result: 1
|
||||
- name: Cast identity -1
|
||||
expression: INT(-1)
|
||||
result: -1
|
||||
- name: Cast from TRUE to int
|
||||
expression: INT(TRUE)
|
||||
result: 1
|
||||
- name: Cast from FALSE to int
|
||||
expression: INT(FALSE)
|
||||
result: 0
|
||||
- name: Invalid cast from string to int
|
||||
expression: INT('ABC')
|
||||
result: 0
|
||||
error: cast
|
||||
|
||||
- name: Cast 'TRUE' to boolean
|
||||
expression: BOOL('TRUE')
|
||||
result: true
|
||||
- name: Cast "false" to boolean
|
||||
expression: BOOL("false")
|
||||
result: false
|
||||
- name: Cast identity TRUE
|
||||
expression: BOOL(TRUE)
|
||||
result: true
|
||||
- name: Cast identity FALSE
|
||||
expression: BOOL(FALSE)
|
||||
result: FALSE
|
||||
- name: Invalid cast from string to boolean
|
||||
expression: BOOL('ABC')
|
||||
result: false
|
||||
error: cast
|
||||
- name: Cast from 1 to boolean
|
||||
expression: BOOL(1)
|
||||
result: true
|
||||
- name: Cast from 0 to boolean
|
||||
expression: BOOL(0)
|
||||
result: false
|
||||
- name: Cast from 100 to boolean
|
||||
expression: BOOL(100)
|
||||
result: true
|
||||
- name: Cast from -50 to boolean
|
||||
expression: BOOL(-50)
|
||||
result: true
|
||||
|
||||
- name: Cast TRUE to string
|
||||
expression: STRING(TRUE)
|
||||
result: 'true'
|
||||
- name: Cast FALSE to string
|
||||
expression: STRING(FALSE)
|
||||
result: 'false'
|
||||
- name: Cast 1 to string
|
||||
expression: STRING(1)
|
||||
result: '1'
|
||||
- name: Cast -1 to string
|
||||
expression: STRING(-1)
|
||||
result: '-1'
|
||||
- name: Cast identity "abc"
|
||||
expression: STRING("abc")
|
||||
result: "abc"
|
|
@ -0,0 +1,53 @@
|
|||
name: Context attributest test
|
||||
tests:
|
||||
- name: Access to required attribute
|
||||
expression: id
|
||||
eventOverrides:
|
||||
id: myId
|
||||
result: myId
|
||||
- name: Access to optional attribute
|
||||
expression: subject
|
||||
eventOverrides:
|
||||
subject: mySubject
|
||||
result: mySubject
|
||||
- name: Absent optional attribute
|
||||
expression: subject
|
||||
event:
|
||||
specversion: "1.0"
|
||||
id: myId
|
||||
source: localhost.localdomain
|
||||
type: myType
|
||||
result: false
|
||||
error: missingAttribute
|
||||
- name: Access to optional boolean extension
|
||||
expression: mybool
|
||||
eventOverrides:
|
||||
mybool: true
|
||||
result: true
|
||||
- name: Access to optional integer extension
|
||||
expression: myint
|
||||
eventOverrides:
|
||||
myint: 10
|
||||
result: 10
|
||||
- name: Access to optional string extension
|
||||
expression: myext
|
||||
eventOverrides:
|
||||
myext: "my extension"
|
||||
result: "my extension"
|
||||
- name: URL type cohercion to string
|
||||
expression: source
|
||||
event:
|
||||
specversion: "1.0"
|
||||
id: myId
|
||||
source: "http://localhost/source"
|
||||
type: myType
|
||||
result: "http://localhost/source"
|
||||
- name: Timestamp type cohercion to string
|
||||
expression: time
|
||||
event:
|
||||
specversion: "1.0"
|
||||
id: myId
|
||||
source: "http://localhost/source"
|
||||
type: myType
|
||||
time: 2018-04-26T14:48:09+02:00
|
||||
result: 2018-04-26T14:48:09+02:00
|
|
@ -0,0 +1,57 @@
|
|||
name: Exists expression
|
||||
tests:
|
||||
- name: required attributes always exist
|
||||
expression: EXISTS specversion AND EXISTS id AND EXISTS type AND EXISTS SOURCE
|
||||
result: true
|
||||
|
||||
- name: optional attribute available
|
||||
expression: EXISTS time
|
||||
event:
|
||||
specversion: "1.0"
|
||||
id: myId
|
||||
source: "http://localhost/source"
|
||||
type: myType
|
||||
time: 2018-04-26T14:48:09+02:00
|
||||
result: true
|
||||
- name: optional attribute absent
|
||||
expression: EXISTS time
|
||||
event:
|
||||
specversion: "1.0"
|
||||
id: myId
|
||||
source: "http://localhost/source"
|
||||
type: myType
|
||||
result: false
|
||||
- name: optional attribute absent (negated)
|
||||
expression: NOT EXISTS time
|
||||
event:
|
||||
specversion: "1.0"
|
||||
id: myId
|
||||
source: "http://localhost/source"
|
||||
type: myType
|
||||
result: true
|
||||
|
||||
- name: optional extension available
|
||||
expression: EXISTS myext
|
||||
event:
|
||||
specversion: "1.0"
|
||||
id: myId
|
||||
source: "http://localhost/source"
|
||||
type: myType
|
||||
myext: my value
|
||||
result: true
|
||||
- name: optional extension absent
|
||||
expression: EXISTS myext
|
||||
event:
|
||||
specversion: "1.0"
|
||||
id: myId
|
||||
source: "http://localhost/source"
|
||||
type: myType
|
||||
result: false
|
||||
- name: optional extension absent (negated)
|
||||
expression: NOT EXISTS myext
|
||||
event:
|
||||
specversion: "1.0"
|
||||
id: myId
|
||||
source: "http://localhost/source"
|
||||
type: myType
|
||||
result: true
|
|
@ -0,0 +1,78 @@
|
|||
name: In expression
|
||||
tests:
|
||||
- name: int in int set
|
||||
expression: 123 IN (1, 2, 3, 12, 13, 23, 123)
|
||||
result: true
|
||||
- name: int not in int set
|
||||
expression: 123 NOT IN (1, 2, 3, 12, 13, 23, 123)
|
||||
result: false
|
||||
|
||||
- name: string in string set
|
||||
expression: "'abc' IN ('abc', \"bcd\")"
|
||||
result: true
|
||||
- name: string not in string set
|
||||
expression: "'aaa' IN ('abc', \"bcd\")"
|
||||
result: false
|
||||
|
||||
- name: bool in bool set
|
||||
expression: TRUE IN (TRUE, FALSE)
|
||||
result: true
|
||||
- name: bool not in bool set
|
||||
expression: TRUE IN (FALSE)
|
||||
result: false
|
||||
|
||||
- name: mix literals and identifiers (1)
|
||||
expression: source IN (myext, 'abc')
|
||||
event:
|
||||
specversion: "1.0"
|
||||
id: myId
|
||||
source: "http://localhost/source"
|
||||
type: myType
|
||||
myext: "http://localhost/source"
|
||||
result: true
|
||||
- name: mix literals and identifiers (2)
|
||||
expression: source IN (source)
|
||||
event:
|
||||
specversion: "1.0"
|
||||
id: myId
|
||||
source: "http://localhost/source"
|
||||
type: myType
|
||||
myext: "http://localhost/source"
|
||||
result: true
|
||||
- name: mix literals and identifiers (3)
|
||||
expression: "source IN (id, \"http://localhost/source\")"
|
||||
event:
|
||||
specversion: "1.0"
|
||||
id: myId
|
||||
source: "http://localhost/source"
|
||||
type: myType
|
||||
myext: "http://localhost/source"
|
||||
result: true
|
||||
- name: mix literals and identifiers (4)
|
||||
expression: source IN (id, 'xyz')
|
||||
event:
|
||||
specversion: "1.0"
|
||||
id: myId
|
||||
source: "http://localhost/source"
|
||||
type: myType
|
||||
result: false
|
||||
|
||||
- name: type coercion with booleans (1)
|
||||
expression: "'true' IN (TRUE, 'false')"
|
||||
result: true
|
||||
- name: type coercion with booleans (2)
|
||||
expression: "'true' IN ('TRUE', 'false')"
|
||||
result: false
|
||||
- name: type coercion with booleans (3)
|
||||
expression: TRUE IN ('true', 'false')
|
||||
result: true
|
||||
- name: type coercion with booleans (4)
|
||||
expression: "'TRUE' IN (TRUE, 'false')"
|
||||
result: false
|
||||
|
||||
- name: type coercion with int (1)
|
||||
expression: "1 IN ('1', '2')"
|
||||
result: true
|
||||
- name: type coercion with int (2)
|
||||
expression: "'1' IN (1, 2)"
|
||||
result: true
|
|
@ -0,0 +1,16 @@
|
|||
name: Integer builtin functions
|
||||
tests:
|
||||
- name: ABS (1)
|
||||
expression: ABS(10)
|
||||
result: 10
|
||||
- name: ABS (2)
|
||||
expression: ABS(-10)
|
||||
result: 10
|
||||
- name: ABS (3)
|
||||
expression: ABS(0)
|
||||
result: 0
|
||||
- name: ABS overflow
|
||||
expression: ABS(-2147483648)
|
||||
result: 2147483647
|
||||
error: math
|
||||
|
|
@ -0,0 +1,129 @@
|
|||
name: Like expression
|
||||
tests:
|
||||
- name: Exact match (1)
|
||||
expression: "'abc' LIKE 'abc'"
|
||||
result: true
|
||||
- name: Exact match (2)
|
||||
expression: "'ab\\c' LIKE 'ab\\c'"
|
||||
result: true
|
||||
- name: Exact match (negate)
|
||||
expression: "'abc' NOT LIKE 'abc'"
|
||||
result: false
|
||||
|
||||
- name: Percentage operator (1)
|
||||
expression: "'abc' LIKE 'a%b%c'"
|
||||
result: true
|
||||
- name: Percentage operator (2)
|
||||
expression: "'azbc' LIKE 'a%b%c'"
|
||||
result: true
|
||||
- name: Percentage operator (3)
|
||||
expression: "'azzzbzzzc' LIKE 'a%b%c'"
|
||||
result: true
|
||||
- name: Percentage operator (4)
|
||||
expression: "'a%b%c' LIKE 'a%b%c'"
|
||||
result: true
|
||||
- name: Percentage operator (5)
|
||||
expression: "'ac' LIKE 'abc'"
|
||||
result: false
|
||||
- name: Percentage operator (6)
|
||||
expression: "'' LIKE 'abc'"
|
||||
result: false
|
||||
- name: Percentage operator (7)
|
||||
expression: "'.ab.cde.' LIKE '.%.%.'"
|
||||
result: true
|
||||
- name: Percentage operator (8)
|
||||
expression: "'ab.cde' LIKE '.%.%.'"
|
||||
result: false
|
||||
|
||||
- name: Underscore operator (1)
|
||||
expression: "'abc' LIKE 'a_b_c'"
|
||||
result: false
|
||||
- name: Underscore operator (2)
|
||||
expression: "'a_b_c' LIKE 'a_b_c'"
|
||||
result: true
|
||||
- name: Underscore operator (3)
|
||||
expression: "'abzc' LIKE 'a_b_c'"
|
||||
result: false
|
||||
- name: Underscore operator (4)
|
||||
expression: "'azbc' LIKE 'a_b_c'"
|
||||
result: false
|
||||
- name: Underscore operator (5)
|
||||
expression: "'azbzc' LIKE 'a_b_c'"
|
||||
result: true
|
||||
- name: Underscore operator (6)
|
||||
expression: "'.a.b.' LIKE '._._.'"
|
||||
result: true
|
||||
- name: Underscore operator (7)
|
||||
expression: "'abcd.' LIKE '._._.'"
|
||||
result: false
|
||||
|
||||
- name: Escaped underscore wildcards (1)
|
||||
expression: "'a_b_c' LIKE 'a\\_b\\_c'"
|
||||
result: true
|
||||
- name: Escaped underscore wildcards (2)
|
||||
expression: "'a_b_c' NOT LIKE 'a\\_b\\_c'"
|
||||
result: false
|
||||
- name: Escaped underscore wildcards (3)
|
||||
expression: "'azbzc' LIKE 'a\\_b\\_c'"
|
||||
result: false
|
||||
- name: Escaped underscore wildcards (4)
|
||||
expression: "'abc' LIKE 'a\\_b\\_c'"
|
||||
result: false
|
||||
|
||||
- name: Escaped percentage wildcards (1)
|
||||
expression: "'abc' LIKE 'a\\%b\\%c'"
|
||||
result: false
|
||||
- name: Escaped percentage wildcards (2)
|
||||
expression: "'a%b%c' LIKE 'a\\%b\\%c'"
|
||||
result: true
|
||||
- name: Escaped percentage wildcards (3)
|
||||
expression: "'azbzc' LIKE 'a\\%b\\%c'"
|
||||
result: false
|
||||
- name: Escaped percentage wildcards (4)
|
||||
expression: "'abc' LIKE 'a\\%b\\%c'"
|
||||
result: false
|
||||
|
||||
- name: With access to event attributes
|
||||
expression: "myext LIKE 'abc%123\\%456\\_d_f'"
|
||||
eventOverrides:
|
||||
myext: "abc123123%456_dzf"
|
||||
result: true
|
||||
- name: With access to event attributes (negated)
|
||||
expression: "myext NOT LIKE 'abc%123\\%456\\_d_f'"
|
||||
eventOverrides:
|
||||
myext: "abc123123%456_dzf"
|
||||
result: false
|
||||
|
||||
- name: With type coercion from int (1)
|
||||
expression: "234 LIKE '23_'"
|
||||
result: true
|
||||
- name: With type coercion from int (2)
|
||||
expression: "2344 LIKE '23%'"
|
||||
result: true
|
||||
- name: With type coercion from int (3)
|
||||
expression: "2344 LIKE '23_'"
|
||||
result: false
|
||||
|
||||
- name: With type coercion from bool (1)
|
||||
expression: "TRUE LIKE 'tr%'"
|
||||
result: true
|
||||
- name: With type coercion from bool (2)
|
||||
expression: "TRUE LIKE '%ue'"
|
||||
result: true
|
||||
- name: With type coercion from bool (3)
|
||||
expression: "FALSE LIKE 'tr%'"
|
||||
result: false
|
||||
- name: With type coercion from bool (4)
|
||||
expression: "FALSE LIKE 'fal%'"
|
||||
result: true
|
||||
|
||||
- name: Invalid string literal in comparison causes parse error
|
||||
expression: "x LIKE 123"
|
||||
result: false
|
||||
error: parse
|
||||
eventOverrides:
|
||||
x: "123"
|
||||
- name: Missing attribute returns empty string
|
||||
expression: "missing LIKE 'missing'"
|
||||
result: false
|
||||
error: missingAttribute
|
|
@ -0,0 +1,36 @@
|
|||
name: Literals
|
||||
tests:
|
||||
- name: TRUE literal
|
||||
expression: TRUE
|
||||
result: true
|
||||
- name: FALSE literal
|
||||
expression: FALSE
|
||||
result: false
|
||||
|
||||
- name: 0 literal
|
||||
expression: 0
|
||||
result: 0
|
||||
- name: 1 literal
|
||||
expression: 1
|
||||
result: 1
|
||||
|
||||
- name: String literal single quoted
|
||||
expression: "'abc'"
|
||||
result: abc
|
||||
- name: String literal double quoted
|
||||
expression: "\"abc\""
|
||||
result: abc
|
||||
|
||||
- name: String literal single quoted with case
|
||||
expression: "'aBc'"
|
||||
result: aBc
|
||||
- name: String literal double quoted with case
|
||||
expression: "\"AbC\""
|
||||
result: AbC
|
||||
|
||||
- name: Escaped string literal (1)
|
||||
expression: "'a\"b\\'c'"
|
||||
result: a"b'c
|
||||
- name: Escaped string literal (2)
|
||||
expression: "\"a'b\\\"c\""
|
||||
result: a'b"c
|
|
@ -0,0 +1,24 @@
|
|||
name: Negate operator
|
||||
tests:
|
||||
- name: Minus 10
|
||||
expression: -10
|
||||
result: -10
|
||||
- name: Minus minus 10
|
||||
expression: --10
|
||||
result: 10
|
||||
|
||||
- name: Minus 10 with casting
|
||||
expression: -'10'
|
||||
result: -10
|
||||
- name: Minus minus 10 with casting
|
||||
expression: --'10'
|
||||
result: 10
|
||||
|
||||
- name: Minus with boolean cast
|
||||
expression: -TRUE
|
||||
result: -1
|
||||
|
||||
- name: Minus with missing attribute
|
||||
expression: -missing
|
||||
result: 0
|
||||
error: missingAttribute
|
|
@ -0,0 +1,25 @@
|
|||
name: Not operator
|
||||
tests:
|
||||
- name: Not true
|
||||
expression: NOT TRUE
|
||||
result: false
|
||||
- name: Not false
|
||||
expression: NOT FALSE
|
||||
result: true
|
||||
|
||||
- name: Not true with casting
|
||||
expression: NOT 'TRUE'
|
||||
result: false
|
||||
- name: Not false 10 with casting
|
||||
expression: NOT 'FALSE'
|
||||
result: true
|
||||
|
||||
- name: Invalid int cast
|
||||
expression: NOT 10
|
||||
result: true
|
||||
error: cast
|
||||
|
||||
- name: Not missing attribute
|
||||
expression: NOT missing
|
||||
result: false
|
||||
error: missingAttribute
|
|
@ -0,0 +1,5 @@
|
|||
name: Parsing errors
|
||||
tests:
|
||||
- name: No closed parenthesis
|
||||
expression: ABC(
|
||||
error: parse
|
|
@ -0,0 +1,77 @@
|
|||
name: Specification examples
|
||||
tests:
|
||||
- name: Case insensitive hops (1)
|
||||
expression: int(hop) < int(ttl) and int(hop) < 1000
|
||||
eventOverrides:
|
||||
hop: '5'
|
||||
ttl: '10'
|
||||
result: true
|
||||
- name: Case insensitive hops (2)
|
||||
expression: INT(hop) < INT(ttl) AND INT(hop) < 1000
|
||||
eventOverrides:
|
||||
hop: '5'
|
||||
ttl: '10'
|
||||
result: true
|
||||
- name: Case insensitive hops (3)
|
||||
expression: hop < ttl
|
||||
eventOverrides:
|
||||
hop: '5'
|
||||
ttl: '10'
|
||||
result: true
|
||||
|
||||
- name: Equals with casting (1)
|
||||
expression: sequence = 5
|
||||
eventOverrides:
|
||||
sequence: '5'
|
||||
result: true
|
||||
- name: Equals with casting (2)
|
||||
expression: sequence = 5
|
||||
eventOverrides:
|
||||
sequence: '6'
|
||||
result: false
|
||||
|
||||
- name: Logic expression (1)
|
||||
expression: firstname = 'Francesco' OR subject = 'Francesco'
|
||||
eventOverrides:
|
||||
subject: Francesco
|
||||
firstname: Doug
|
||||
result: true
|
||||
- name: Logic expression (2)
|
||||
expression: firstname = 'Francesco' OR subject = 'Francesco'
|
||||
eventOverrides:
|
||||
firstname: Francesco
|
||||
subject: Doug
|
||||
result: true
|
||||
- name: Logic expression (3)
|
||||
expression: (firstname = 'Francesco' AND lastname = 'Guardiani') OR subject = 'Francesco Guardiani'
|
||||
eventOverrides:
|
||||
subject: Doug
|
||||
firstname: Francesco
|
||||
lastname: Guardiani
|
||||
result: true
|
||||
- name: Logic expression (4)
|
||||
expression: (firstname = 'Francesco' AND lastname = 'Guardiani') OR subject = 'Francesco Guardiani'
|
||||
eventOverrides:
|
||||
subject: Francesco Guardiani
|
||||
firstname: Doug
|
||||
lastname: Davis
|
||||
result: true
|
||||
|
||||
- name: Subject exists
|
||||
expression: EXISTS subject
|
||||
eventOverrides:
|
||||
subject: Francesco Guardiani
|
||||
result: true
|
||||
|
||||
- name: Missing attribute (1)
|
||||
expression: true AND (missing = "")
|
||||
result: false
|
||||
error: missingAttribute
|
||||
- name: Missing attribute (2)
|
||||
expression: missing * 5
|
||||
result: 0
|
||||
error: missingAttribute
|
||||
- name: Missing attribute (3)
|
||||
expression: 1 / missing
|
||||
result: 0
|
||||
error: missingAttribute
|
|
@ -0,0 +1,143 @@
|
|||
name: String builtin functions
|
||||
tests:
|
||||
- name: LENGTH (1)
|
||||
expression: "LENGTH('abc')"
|
||||
result: 3
|
||||
- name: LENGTH (2)
|
||||
expression: "LENGTH('')"
|
||||
result: 0
|
||||
- name: LENGTH (3)
|
||||
expression: "LENGTH('2')"
|
||||
result: 1
|
||||
- name: LENGTH (4)
|
||||
expression: "LENGTH(TRUE)"
|
||||
result: 4
|
||||
|
||||
- name: CONCAT (1)
|
||||
expression: "CONCAT('a', 'b', 'c')"
|
||||
result: abc
|
||||
- name: CONCAT (2)
|
||||
expression: "CONCAT()"
|
||||
result: ""
|
||||
- name: CONCAT (3)
|
||||
expression: "CONCAT('a')"
|
||||
result: "a"
|
||||
|
||||
- name: CONCAT_WS (1)
|
||||
expression: "CONCAT_WS(',', 'a', 'b', 'c')"
|
||||
result: a,b,c
|
||||
- name: CONCAT_WS (2)
|
||||
expression: "CONCAT_WS(',')"
|
||||
result: ""
|
||||
- name: CONCAT_WS (3)
|
||||
expression: "CONCAT_WS(',', 'a')"
|
||||
result: "a"
|
||||
- name: CONCAT_WS without arguments doesn't exist
|
||||
expression: CONCAT_WS()
|
||||
error: missingFunction
|
||||
result: false
|
||||
|
||||
- name: LOWER (1)
|
||||
expression: "LOWER('ABC')"
|
||||
result: abc
|
||||
- name: LOWER (2)
|
||||
expression: "LOWER('AbC')"
|
||||
result: abc
|
||||
- name: LOWER (3)
|
||||
expression: "LOWER('abc')"
|
||||
result: abc
|
||||
|
||||
- name: UPPER (1)
|
||||
expression: "UPPER('ABC')"
|
||||
result: ABC
|
||||
- name: UPPER (2)
|
||||
expression: "UPPER('AbC')"
|
||||
result: ABC
|
||||
- name: UPPER (3)
|
||||
expression: "UPPER('abc')"
|
||||
result: ABC
|
||||
|
||||
- name: TRIM (1)
|
||||
expression: "TRIM(' a b c ')"
|
||||
result: "a b c"
|
||||
- name: TRIM (2)
|
||||
expression: "TRIM(' a b c')"
|
||||
result: "a b c"
|
||||
- name: TRIM (3)
|
||||
expression: "TRIM('a b c ')"
|
||||
result: "a b c"
|
||||
- name: TRIM (4)
|
||||
expression: "TRIM('a b c')"
|
||||
result: "a b c"
|
||||
|
||||
- name: LEFT (1)
|
||||
expression: LEFT('abc', 2)
|
||||
result: ab
|
||||
- name: LEFT (2)
|
||||
expression: LEFT('abc', 10)
|
||||
result: abc
|
||||
- name: LEFT (3)
|
||||
expression: LEFT('', 0)
|
||||
result: ""
|
||||
- name: LEFT (4)
|
||||
expression: LEFT('abc', -2)
|
||||
result: "abc"
|
||||
error: functionEvaluation
|
||||
|
||||
- name: RIGHT (1)
|
||||
expression: RIGHT('abc', 2)
|
||||
result: bc
|
||||
- name: RIGHT (2)
|
||||
expression: RIGHT('abc', 10)
|
||||
result: abc
|
||||
- name: RIGHT (3)
|
||||
expression: RIGHT('', 0)
|
||||
result: ""
|
||||
- name: RIGHT (4)
|
||||
expression: RIGHT('abc', -2)
|
||||
result: "abc"
|
||||
error: functionEvaluation
|
||||
|
||||
- name: SUBSTRING (1)
|
||||
expression: "SUBSTRING('abcdef', 1)"
|
||||
result: "abcdef"
|
||||
- name: SUBSTRING (2)
|
||||
expression: "SUBSTRING('abcdef', 2)"
|
||||
result: "bcdef"
|
||||
- name: SUBSTRING (3)
|
||||
expression: "SUBSTRING('Quadratically', 5)"
|
||||
result: "ratically"
|
||||
- name: SUBSTRING (4)
|
||||
expression: "SUBSTRING('Sakila', -3)"
|
||||
result: "ila"
|
||||
- name: SUBSTRING (5)
|
||||
expression: "SUBSTRING('abcdef', 1, 6)"
|
||||
result: "abcdef"
|
||||
- name: SUBSTRING (6)
|
||||
expression: "SUBSTRING('abcdef', 2, 4)"
|
||||
result: "bcde"
|
||||
- name: SUBSTRING (7)
|
||||
expression: "SUBSTRING('Sakila', -5, 3)"
|
||||
result: "aki"
|
||||
- name: SUBSTRING (8)
|
||||
expression: "SUBSTRING('Quadratically', 0)"
|
||||
result: ""
|
||||
- name: SUBSTRING (9)
|
||||
expression: "SUBSTRING('Quadratically', 0, 1)"
|
||||
result: ""
|
||||
- name: SUBSTRING (10)
|
||||
expression: "SUBSTRING('abcdef', 10)"
|
||||
result: ""
|
||||
error: functionEvaluation
|
||||
- name: SUBSTRING (11)
|
||||
expression: "SUBSTRING('abcdef', -10)"
|
||||
result: ""
|
||||
error: functionEvaluation
|
||||
- name: SUBSTRING (12)
|
||||
expression: "SUBSTRING('abcdef', 10, 10)"
|
||||
result: ""
|
||||
error: functionEvaluation
|
||||
- name: SUBSTRING (13)
|
||||
expression: "SUBSTRING('abcdef', -10, 10)"
|
||||
result: ""
|
||||
error: functionEvaluation
|
|
@ -0,0 +1,12 @@
|
|||
name: Sub expressions
|
||||
tests:
|
||||
- name: Sub expression with literal
|
||||
expression: "(TRUE)"
|
||||
result: true
|
||||
|
||||
- name: Math (1)
|
||||
expression: "4 * (2 + 3)"
|
||||
result: 20
|
||||
- name: Math (2)
|
||||
expression: "(2 + 3) * 4"
|
||||
result: 20
|
|
@ -0,0 +1,173 @@
|
|||
name: SubscriptionsAPI Recreations
|
||||
tests:
|
||||
- name: Prefix filter (1)
|
||||
expression: "source LIKE 'https://%'"
|
||||
result: true
|
||||
eventOverrides:
|
||||
source: "https://example.com"
|
||||
- name: Prefix filter (2)
|
||||
expression: "source LIKE 'https://%'"
|
||||
result: false
|
||||
eventOverrides:
|
||||
source: "http://example.com"
|
||||
- name: Prefix filter on string extension
|
||||
expression: "myext LIKE 'custom%'"
|
||||
result: true
|
||||
eventOverrides:
|
||||
myext: "customext"
|
||||
- name: Prefix filter on missing string extension
|
||||
expression: "myext LIKE 'custom%'"
|
||||
result: false
|
||||
error: missingAttribute
|
||||
|
||||
- name: Suffix filter (1)
|
||||
expression: "type like '%.error'"
|
||||
result: true
|
||||
eventOverrides:
|
||||
type: "com.github.error"
|
||||
- name: Suffix filter (2)
|
||||
expression: "type like '%.error'"
|
||||
result: false
|
||||
eventOverrides:
|
||||
type: "com.github.success"
|
||||
- name: Suffix filter on string extension
|
||||
expression: "myext LIKE '%ext'"
|
||||
result: true
|
||||
eventOverrides:
|
||||
myext: "customext"
|
||||
- name: Suffix filter on missing string extension
|
||||
expression: "myext LIKE '%ext'"
|
||||
result: false
|
||||
error: missingAttribute
|
||||
|
||||
- name: Exact filter (1)
|
||||
expression: "id = 'myId'"
|
||||
result: true
|
||||
eventOverrides:
|
||||
id: "myId"
|
||||
- name: Exact filter (2)
|
||||
expression: "id = 'myId'"
|
||||
result: false
|
||||
eventOverrides:
|
||||
id: "notmyId"
|
||||
- name: Exact filter on string extension
|
||||
expression: "myext = 'customext'"
|
||||
result: true
|
||||
eventOverrides:
|
||||
myext: "customext"
|
||||
- name: Exact filter on missing string extension
|
||||
expression: "myext = 'customext'"
|
||||
result: false
|
||||
error: missingAttribute
|
||||
|
||||
- name: Prefix filter AND Suffix filter (1)
|
||||
expression: "id LIKE 'my%' AND source LIKE '%.ca'"
|
||||
result: true
|
||||
eventOverrides:
|
||||
id: "myId"
|
||||
source: "http://www.some-website.ca"
|
||||
- name: Prefix filter AND Suffix filter (2)
|
||||
expression: "id LIKE 'my%' AND source LIKE '%.ca'"
|
||||
result: false
|
||||
eventOverrides:
|
||||
id: "myId"
|
||||
source: "http://www.some-website.com"
|
||||
- name: Prefix filter AND Suffix filter (3)
|
||||
expression: "myext LIKE 'custom%' AND type LIKE '%.error'"
|
||||
result: true
|
||||
eventOverrides:
|
||||
myext: "customext"
|
||||
type: "com.github.error"
|
||||
- name: Prefix AND Suffix filter (4)
|
||||
expression: "type LIKE 'example.%' AND myext LIKE 'custom%'"
|
||||
result: false
|
||||
eventOverrides:
|
||||
type: "example.event.type"
|
||||
error: missingAttribute
|
||||
|
||||
- name: Prefix OR Suffix filter (1)
|
||||
expression: "id LIKE 'my%' OR source LIKE '%.ca'"
|
||||
result: true
|
||||
eventOverrides:
|
||||
id: "myId"
|
||||
source: "http://www.some-website.ca"
|
||||
- name: Prefix OR Suffix filter (2)
|
||||
expression: "id LIKE 'my%' OR source LIKE '%.ca'"
|
||||
result: true
|
||||
eventOverrides:
|
||||
id: "myId"
|
||||
source: "http://www.some-website.com"
|
||||
- name: Prefix OR Suffix filter (3)
|
||||
expression: "id LIKE 'my%' OR source LIKE '%.ca'"
|
||||
result: true
|
||||
eventOverrides:
|
||||
id: "notmyId"
|
||||
source: "http://www.some-website.ca"
|
||||
- name: Prefix OR Suffix filter (4)
|
||||
expression: "id LIKE 'my%' OR source LIKE '%.ca'"
|
||||
result: false
|
||||
eventOverrides:
|
||||
id: "notmyId"
|
||||
source: "http://www.some-website.com"
|
||||
|
||||
- name: Disjunctive Normal Form (1)
|
||||
expression: "(id = 'myId' AND type LIKE '%.success') OR (id = 'notmyId' AND source LIKE 'http://%' AND type LIKE '%.warning')"
|
||||
result: true
|
||||
eventOverrides:
|
||||
id: "myId"
|
||||
type: "example.event.success"
|
||||
- name: Disjunctive Normal Form (2)
|
||||
expression: "(id = 'myId' AND type LIKE '%.success') OR (id = 'notmyId' AND source LIKE 'http://%' AND type LIKE '%.warning')"
|
||||
result: true
|
||||
eventOverrides:
|
||||
id: "notmyId"
|
||||
type: "example.event.warning"
|
||||
source: "http://localhost.localdomain"
|
||||
- name: Disjunctive Normal Form (3)
|
||||
expression: "(id = 'myId' AND type LIKE '%.success') OR (id = 'notmyId' AND source LIKE 'http://%' AND type LIKE '%.warning')"
|
||||
result: false
|
||||
eventOverrides:
|
||||
id: "notmyId"
|
||||
type: "example.event.warning"
|
||||
source: "https://localhost.localdomain"
|
||||
|
||||
- name: Conjunctive Normal Form (1)
|
||||
expression: "(id = 'myId' OR type LIKE '%.success') AND (id = 'notmyId' OR source LIKE 'https://%' OR type LIKE '%.warning')"
|
||||
result: true
|
||||
eventOverrides:
|
||||
id: "myId"
|
||||
type: "example.event.warning"
|
||||
source: "http://localhost.localdomain"
|
||||
- name: Conjunctive Normal Form (2)
|
||||
expression: "(id = 'myId' OR type LIKE '%.success') AND (id = 'notmyId' OR source LIKE 'https://%' OR type LIKE '%.warning')"
|
||||
result: true
|
||||
eventOverrides:
|
||||
id: "notmyId"
|
||||
type: "example.event.success"
|
||||
source: "http://localhost.localdomain"
|
||||
- name: Conjunctive Normal Form (3)
|
||||
expression: "(id = 'myId' OR type LIKE '%.success') AND (id = 'notmyId' OR source LIKE 'https://%' OR type LIKE '%.warning')"
|
||||
result: false
|
||||
eventOverrides:
|
||||
id: "notmyId"
|
||||
type: "example.event.warning"
|
||||
source: "http://localhost.localdomain"
|
||||
- name: Conjunctive Normal Form (4)
|
||||
expression: "(id = 'myId' OR type LIKE '%.success') AND (id = 'notmyId' OR source LIKE 'https://%' OR type LIKE '%.warning')"
|
||||
result: false
|
||||
eventOverrides:
|
||||
id: "myId"
|
||||
type: "example.event.success"
|
||||
source: "http://localhost.localdomain"
|
||||
- name: Conjunctive Normal Form (5)
|
||||
expression: "(id = 'myId' OR type LIKE '%.success') AND (id = 'notmyId' OR source LIKE 'https://%' OR type LIKE '%.warning') AND (myext = 'customext')"
|
||||
result: false
|
||||
eventOverrides:
|
||||
id: "myId"
|
||||
type: "example.event.warning"
|
||||
source: "http://localhost.localdomain"
|
||||
error: missingAttribute
|
||||
|
||||
|
||||
|
||||
|
|
@ -0,0 +1,3 @@
|
|||
# CESQL v1.0.0 (制作中)
|
||||
|
||||
请参阅[CESQL 规范](spec.md)
|
|
@ -0,0 +1,6 @@
|
|||
# CESQL 规范发行信息
|
||||
|
||||
<!-- no verify-specs -->
|
||||
|
||||
## vX.Y.Z - YYYY/MM/DD
|
||||
- 尚未发行 (#000)
|
|
@ -0,0 +1,6 @@
|
|||
# CloudEvents Expression Language TCK
|
||||
|
||||
本文档尚未被翻译,请先阅读英文[原版文档](../../../cesql_tck/README.md) 。
|
||||
|
||||
如果您迫切地需要此文档的中文翻译,请[提交一个issue](https://github.com/cloudevents/spec/issues) ,
|
||||
我们会尽快安排专人进行翻译。
|
|
@ -0,0 +1,6 @@
|
|||
# CloudEvents SQL Expression Language - Version 1.0.0
|
||||
|
||||
本文档尚未被翻译,请先阅读英文[原版文档](../../spec.md) 。
|
||||
|
||||
如果您迫切地需要此文档的中文翻译,请[提交一个issue](https://github.com/cloudevents/spec/issues) ,
|
||||
我们会尽快安排专人进行翻译。
|
|
@ -0,0 +1,8 @@
|
|||
# Translation list of the cesql spec
|
||||
|
||||
| Documents | Status | Last edited | Version |
|
||||
| :--------- | :---------: | :--------- | :---------: |
|
||||
| /cesql/README.md | PR reviewing | 2022-03-26T13:55:02.773Z | - |
|
||||
| /cesql/RELEASE_NOTES.md | PR reviewing | 2022-03-26T14:00:58.009Z | - |
|
||||
| /cesql/spec.md | Ready to start | | |
|
||||
| /cesql/cesql_tck/README.md | Ready to start | | |
|
|
@ -0,0 +1,658 @@
|
|||
# CloudEvents SQL Expression Language - Version 1.0.0
|
||||
|
||||
## Abstract
|
||||
|
||||
The goal of this specification is to define a SQL-like expression language
|
||||
which can be used to express predicates on CloudEvent instances.
|
||||
|
||||
## Table of Contents
|
||||
|
||||
1. [Introduction](#1-introduction)
|
||||
|
||||
- 1.1. [Conformance](#11-conformance)
|
||||
- 1.2. [Relation to Subscriptions API](#12-relation-to-the-subscriptions-api)
|
||||
|
||||
2. [Language syntax](#2-language-syntax)
|
||||
|
||||
- 2.1. [Expression](#21-expression)
|
||||
- 2.2. [Value identifiers and literals](#22-value-identifiers-and-literals)
|
||||
- 2.3. [Operators](#23-operators)
|
||||
- 2.4. [Function invocations](#24-function-invocations)
|
||||
|
||||
3. [Language semantics](#3-language-semantics)
|
||||
|
||||
- 3.1. [Type system](#31-type-system)
|
||||
- 3.2. [CloudEvent context identifiers and types](#32-cloudevent-context-identifiers-and-types)
|
||||
- 3.3. [Errors](#33-errors)
|
||||
- 3.4. [Operators](#34-operators)
|
||||
- 3.5. [Functions](#35-functions)
|
||||
- 3.6. [Evaluation of the expression](#36-evaluation-of-the-expression)
|
||||
- 3.7. [Type casting](#37-type-casting)
|
||||
|
||||
4. [Implementation suggestions](#4-implementation-suggestions)
|
||||
|
||||
- 4.1. [Error handling](#41-error-handling)
|
||||
|
||||
5. [Examples](#5-examples)
|
||||
6. [References](#6-references)
|
||||
|
||||
## 1. Introduction
|
||||
|
||||
CloudEvents SQL expressions (also known as CESQL) allow computing values and
|
||||
matching of CloudEvent attributes against complex expressions that lean on the
|
||||
syntax of Structured Query Language (SQL) `WHERE` clauses. Using SQL-derived
|
||||
expressions for message filtering has widespread implementation usage because
|
||||
the Java Message Service (JMS) message selector syntax also leans on SQL. Note
|
||||
that neither the [SQL standard (ISO 9075)][iso-9075] nor the JMS standard nor
|
||||
any other SQL dialect is used as a normative foundation or to constrain the
|
||||
expression syntax defined in this specification, but the syntax is informed by
|
||||
them.
|
||||
|
||||
CESQL is a _[total pure functional programming
|
||||
language][total-programming-language-wiki]_ in order to guarantee the
|
||||
termination of the evaluation of the expression. It features a type system
|
||||
correlated to the [CloudEvents type
|
||||
system][ce-type-system], and it features boolean and arithmetic operations,
|
||||
as well as built-in functions for string manipulation.
|
||||
|
||||
The language is not constrained to a particular execution environment, which
|
||||
means it might run in a source, in a producer, or in an intermediary, and it
|
||||
can be implemented using any technology stack.
|
||||
|
||||
The CloudEvents Expression Language assumes the input always includes, but is
|
||||
not limited to, a single valid and type-checked CloudEvent instance. An
|
||||
expression MUST NOT mutate the value of the input CloudEvent instance, nor any
|
||||
of the other input values. The evaluation of an expression observes the concept
|
||||
of [referential transparency][referential-transparency-wiki]. This means that
|
||||
any part of an expression can be replaced with its output value and the overall
|
||||
result of the expression will be unchanged. The primary output of a CESQL
|
||||
expression evaluation is always a _boolean_, an _integer_ or a _string_. The
|
||||
secondary output of a CESQL expression evaluation is a set of errors which
|
||||
occurred during evaluation. This set MAY be empty, indicating that no error
|
||||
occurred during execution of the expression. The values used by CESQL engines
|
||||
to represent a set of errors (empty or not) is out of the scope of this
|
||||
specification.
|
||||
|
||||
The CloudEvents Expression Language doesn't support the handling of the data
|
||||
field of the CloudEvent instances, due to its polymorphic nature and
|
||||
complexity. Users that need this functionality ought to use other more
|
||||
appropriate tools.
|
||||
|
||||
### 1.1. Conformance
|
||||
|
||||
The key words "MUST", "MUST NOT", "REQUIRED", "SHALL", "SHALL NOT", "SHOULD",
|
||||
"SHOULD NOT", "RECOMMENDED", "MAY", and "OPTIONAL" in this document are to be
|
||||
interpreted as described in [RFC2119][rfc2119].
|
||||
|
||||
### 1.2. Relation to the Subscriptions API
|
||||
|
||||
The CESQL can be used as a [filter dialect][subscriptions-filter-dialect] to
|
||||
filter on the input values.
|
||||
|
||||
When used as a filter predicate, the expression output value MUST be a
|
||||
_Boolean_. If the output value is not a _Boolean_, or any errors are returned,
|
||||
the event MUST NOT pass the filter. Due to the requirement that events MUST NOT
|
||||
pass the filter if any errors occur, when used in a filtering context the CESQL
|
||||
engine SHOULD follow the "fail fast mode" error handling described in section
|
||||
4.1.
|
||||
|
||||
## 2. Language syntax
|
||||
|
||||
The grammar of the language is defined using the EBNF Notation from [W3C XML
|
||||
specification][ebnf-xml-spec].
|
||||
|
||||
Although in the EBNF keywords are defined using uppercase characters, they are
|
||||
case-insensitive. For example:
|
||||
|
||||
```
|
||||
int(hop) < int(ttl) and int(hop) < 1000
|
||||
```
|
||||
|
||||
Has the same syntactical meaning of:
|
||||
|
||||
```
|
||||
INT(hop) < INT(ttl) AND INT(hop) < 1000
|
||||
```
|
||||
|
||||
### 2.1 Expression
|
||||
|
||||
The root of the expression is the `expression` rule:
|
||||
|
||||
```ebnf
|
||||
expression ::= value-identifier | literal | unary-operation | binary-operation | function-invocation | like-operation | exists-operation | in-operation | ( "(" expression ")" )
|
||||
```
|
||||
|
||||
Nested expressions MUST be correctly parenthesized.
|
||||
|
||||
### 2.2. Value identifiers and literals
|
||||
|
||||
Value identifiers in CESQL MUST follow the same restrictions of the [Attribute
|
||||
Naming Convention][ce-attribute-naming-convention] from the CloudEvents spec. A
|
||||
value identifier SHOULD NOT be greater than 20 characters in length.
|
||||
|
||||
```ebnf
|
||||
lowercase-char ::= [a-z]
|
||||
value-identifier ::= ( lowercase-char | digit )+
|
||||
```
|
||||
|
||||
CESQL defines 3 different literal kinds: integer numbers, `true` or `false`
|
||||
booleans, and `''` or `""` delimited strings. Integer literals MUST be valid 32
|
||||
bit signed integer values.
|
||||
|
||||
```ebnf
|
||||
digit ::= [0-9]
|
||||
integer-literal ::= ( '+' | '-' )? digit+
|
||||
|
||||
boolean-literal ::= "true" | "false" (* Case insensitive *)
|
||||
|
||||
string-literal ::= ( "'" ( [^'] | "\'" )* "'" ) | ( '"' ( [^"] | '\"' )* '"')
|
||||
|
||||
literal ::= integer-literal | boolean-literal | string-literal
|
||||
```
|
||||
|
||||
Because string literals can be either `''` or `""` delimited, in the former
|
||||
case, the `'` character has to be escaped if it is to be used in the string
|
||||
literal, while in the latter the `"` has to be escaped if it is to be used in
|
||||
the string literal.
|
||||
|
||||
### 2.3. Operators
|
||||
|
||||
CESQL defines boolean unary and binary operators, arithmetic unary and binary
|
||||
operators, and the `LIKE`, `IN`, `EXISTS` operators.
|
||||
|
||||
```ebnf
|
||||
not-operator ::= "NOT"
|
||||
unary-logic-operator ::= not-operator
|
||||
binary-logic-operator ::= "AND" | "OR" | "XOR"
|
||||
|
||||
unary-numeric-operator ::= "-"
|
||||
binary-comparison-operator ::= "=" | "!=" | "<>" | ">=" | "<=" | "<" | ">"
|
||||
binary-numeric-arithmetic-operator ::= "+" | "-" | "*" | "/" | "%"
|
||||
|
||||
like-operator ::= "LIKE"
|
||||
exists-operator ::= "EXISTS"
|
||||
in-operator ::= "IN"
|
||||
|
||||
unary-operation ::= (unary-numeric-operator | unary-logic-operator) expression
|
||||
|
||||
binary-operation ::= expression (binary-comparison-operator | binary-numeric-arithmetic-operator | binary-logic-operator) expression
|
||||
|
||||
like-operation ::= expression not-operator? like-operator string-literal
|
||||
|
||||
exists-operation ::= exists-operator value-identifier
|
||||
|
||||
set-expression ::= "(" expression ("," expression)* ")"
|
||||
in-operation ::= expression not-operator? in-operator set-expression
|
||||
```
|
||||
|
||||
### 2.4. Function invocations
|
||||
|
||||
CESQL supports n-ary function invocation:
|
||||
|
||||
```ebnf
|
||||
char ::= [A-Z] | [a-z]
|
||||
argument ::= expression
|
||||
|
||||
function-identifier ::= char ( "_" | char )*
|
||||
|
||||
argument-list ::= argument ("," argument)*
|
||||
function-invocation ::= function-identifier "(" argument-list? ")"
|
||||
```
|
||||
|
||||
## 3. Language semantics
|
||||
|
||||
### 3.1. Type system
|
||||
|
||||
The type system contains 3 _primitive_ types:
|
||||
|
||||
- _String_: Sequence of Unicode characters.
|
||||
- _Integer_: A whole number in the range -2,147,483,648 to +2,147,483,647
|
||||
inclusive. This is the range of a signed, 32-bit, twos-complement encoding.
|
||||
- _Boolean_: A boolean value of "true" or "false".
|
||||
|
||||
For each of the 3 _primitive_ types there is an associated zero value, which
|
||||
can be thought of as the "default" value for that type:
|
||||
|
||||
| Type | Zero Value |
|
||||
| --------- | ---------- |
|
||||
| _String_ | `""` |
|
||||
| _Integer_ | `0` |
|
||||
| _Boolean_ | `false` |
|
||||
|
||||
The types _URI_, _URI Reference_, and _Timestamp_ ([defined in the CloudEvents
|
||||
specification][ce-type-system]) are represented as _String_.
|
||||
|
||||
The type system also includes _Set_, which is an unordered collection of
|
||||
_Strings_ of arbitrary length. This type can be used in the `IN` operator.
|
||||
|
||||
### 3.2. CloudEvent context identifiers and types
|
||||
|
||||
Each CloudEvent context attribute and extension MUST be addressable from an
|
||||
expression using its identifier, as defined by the spec. For example, using
|
||||
`id` in an expression will address the CloudEvent [id
|
||||
attribute][ce-id-attribute].
|
||||
|
||||
If the value of the attribute or extension is not one of the primitive CESQL
|
||||
types, it MUST be represented by the _String_ type.
|
||||
|
||||
When addressing an attribute not included in the input event, the subexpression
|
||||
referencing the missing attribute MUST evaluate to the zero value for the
|
||||
return type of the subexpression,along with a _MissingAttributeError_. For
|
||||
example, `true AND (missingAttribute = "")` would evaluate to
|
||||
`false, (missingAttributeError)` as the subexpression `missingAttribute = ""`
|
||||
would be false, given that the return type for the `=` operator is _Boolean_.
|
||||
However, the expression `missingattribute * 5` would evaluate to
|
||||
`0, (missingAttributeError)` because the return type for the `*` operator is
|
||||
_Integer_. Note that this does not mean that the _value_ of the missing
|
||||
attribute is set to be the zero value for the type of the missing attribute.
|
||||
Rather, the subexpression with the missingAttribute returns the zero value of
|
||||
the return type of the subexpression. As an example, `1 / missingAttribute`
|
||||
does not raise a _MathError_ due to the division by zero, instead it returns
|
||||
`0, (missingAttributeError)` as that is the zero value for the return type of
|
||||
the subexpression.
|
||||
|
||||
In cases where the return type of the subexpression cannot be determined by the
|
||||
CESQL engine, the CESQL engine MUST assume a return type of _Boolean_. In such
|
||||
cases, the return value would therefore be `false, (missingAttributeError)`.
|
||||
|
||||
### 3.3. Errors
|
||||
|
||||
Because every operator and function is total, an expression evaluation flow is
|
||||
defined statically and cannot be modified by expected or unexpected errors.
|
||||
Nevertheless CESQL includes the concept of errors: when an expression is
|
||||
evaluated, in case an error arises, the evaluator collects a list of errors,
|
||||
referred in this spec as _error list_, which is then returned together with the
|
||||
evaluated value of the CESQL expression.
|
||||
|
||||
Whenever possible, some error checks SHOULD be done at compile time by the
|
||||
expression evaluator, in order to prevent runtime errors.
|
||||
|
||||
Every CESQL engine MUST support the following error types:
|
||||
|
||||
- _ParseError_: An error that occurs during parsing
|
||||
- _MathError_: An error that occurs during the evaluation of a mathematical
|
||||
operation
|
||||
- _CastError_: An error that occurs during an implicit or explicit type cast
|
||||
- _MissingAttributeError_: An error that occurs when addressing an attribute
|
||||
which is not present on the input event
|
||||
- _MissingFunctionError_: An error that occurs due to a call to a function
|
||||
that has not been registered with the CESQL engine
|
||||
- _FunctionEvaluationError_: An error that occurs during the evaluation of a
|
||||
function
|
||||
- _GenericError_: Any error not specified above
|
||||
|
||||
Whenever an operator or function encounters an error, it MUST result in a
|
||||
"return value" as well as one or more "error values". In cases where there is
|
||||
not an obvious "return value" for the expression, the operator or function
|
||||
SHOULD return the zero value for the return type of the operator or function.
|
||||
|
||||
### 3.4. Operators
|
||||
|
||||
The following tables show the operators that MUST be supported by a CESQL
|
||||
evaluator. When evaluating an operator, a CESQL engine MUST attempt to cast the
|
||||
operands to the specified types.
|
||||
|
||||
#### 3.4.1. Unary operators
|
||||
|
||||
Corresponds to the syntactic rule `unary-operation`:
|
||||
|
||||
| Definition | Semantics |
|
||||
| --------------------------- | ------------------------------- |
|
||||
| `NOT x: Boolean -> Boolean` | Returns the negate value of `x` |
|
||||
| `-x: Integer -> Integer` | Returns the minus value of `x` |
|
||||
|
||||
#### 3.4.2. Binary operators
|
||||
|
||||
Corresponds to the syntactic rule `binary-operation`:
|
||||
|
||||
| Definition | Semantics |
|
||||
| --------------------------------------- | -------------------------------------------------------------------------------------------------------------------------------- |
|
||||
| `x = y: Boolean x Boolean -> Boolean` | Returns `true` if the values of `x` and `y` are equal |
|
||||
| `x != y: Boolean x Boolean -> Boolean` | Same as `NOT (x = y)` |
|
||||
| `x <> y: Boolean x Boolean -> Boolean` | Same as `NOT (x = y)` |
|
||||
| `x AND y: Boolean x Boolean -> Boolean` | Returns the logical and of `x` and `y` |
|
||||
| `x OR y: Boolean x Boolean -> Boolean` | Returns the logical or of `x` and `y` |
|
||||
| `x XOR y: Boolean x Boolean -> Boolean` | Returns the logical xor of `x` and `y` |
|
||||
| `x = y: Integer x Integer -> Boolean` | Returns `true` if the values of `x` and `y` are equal |
|
||||
| `x != y: Integer x Integer -> Boolean` | Same as `NOT (x = y)` |
|
||||
| `x <> y: Integer x Integer -> Boolean` | Same as `NOT (x = y)` |
|
||||
| `x < y: Integer x Integer -> Boolean` | Returns `true` if `x` is less than `y` |
|
||||
| `x <= y: Integer x Integer -> Boolean` | Returns `true` if `x` is less than or equal to `y` |
|
||||
| `x > y: Integer x Integer -> Boolean` | Returns `true` if `x` is greater than `y` |
|
||||
| `x >= y: Integer x Integer -> Boolean` | Returns `true` if `x` is greater than or equal to `y` |
|
||||
| `x * y: Integer x Integer -> Integer` | Returns the product of `x` and `y` |
|
||||
| `x / y: Integer x Integer -> Integer` | Returns the result of dividing `x` by `y`, rounded towards `0` to obtain an integer. Returns `0` and a _MathError_ if `y = 0` |
|
||||
| `x % y: Integer x Integer -> Integer` | Returns the remainder of `x` divided by `y`, where the result has the same sign as `x`. Returns `0` and a _MathError_ if `y = 0` |
|
||||
| `x + y: Integer x Integer -> Integer` | Returns the sum of `x` and `y` |
|
||||
| `x - y: Integer x Integer -> Integer` | Returns the value of `y` subtracted from `x` |
|
||||
| `x = y: String x String -> Boolean` | Returns `true` if the values of `x` and `y` are equal (case sensitive) |
|
||||
| `x != y: String x String -> Boolean` | Same as `NOT (x = y)` (case sensitive) |
|
||||
| `x <> y: String x String -> Boolean` | Same as `NOT (x = y)` (case sensitive) |
|
||||
|
||||
The AND and OR operators MUST be short-circuit evaluated. This means that
|
||||
whenever the left operand of the AND operation evaluates to `false`, the right
|
||||
operand MUST NOT be evaluated. Similarly, whenever the left operand of the OR
|
||||
operation evaluates to `true`, the right operand MUST NOT be evaluated.
|
||||
|
||||
#### 3.4.3. Like operator
|
||||
|
||||
| Definition | Semantics |
|
||||
| ------------------------------------------------ | --------------------------------------------------- |
|
||||
| `x LIKE pattern: String x String -> Boolean` | Returns `true` if the value x matches the `pattern` |
|
||||
| `x NOT LIKE pattern: String x String -> Boolean` | Same as `NOT (x LIKE PATTERN)` |
|
||||
|
||||
The pattern of the `LIKE` operator MUST be a string literal, and can contain:
|
||||
|
||||
- `%` represents zero, one, or multiple characters
|
||||
- `_` represents a single character
|
||||
- Any other character, representing exactly that character (case sensitive)
|
||||
|
||||
For example, the pattern `_b*` will accept values `ab`, `abc`, `abcd1` but
|
||||
won't accept values `b` or `acd` or `aBc`.
|
||||
|
||||
Both `%` and `_` can be escaped with `\`, in order to be matched literally.
|
||||
For example, the pattern `abc\%` will match `abc%` but won't match `abcd`.
|
||||
|
||||
In cases where the left operand is not a `String`, it MUST be cast to a
|
||||
`String` before the comparison is made. The pattern of the `LIKE` operator
|
||||
(that is, the right operand of the operator) MUST be a valid string literal
|
||||
without casting, otherwise the parser MUST return a parse error.
|
||||
|
||||
#### 3.4.4. Exists operator
|
||||
|
||||
| Definition | Semantics |
|
||||
| ----------------------------------- | --------------------------------------------------------------------------- |
|
||||
| `EXISTS identifier: Any -> Boolean` | Returns `true` if the attribute `identifier` exists in the input CloudEvent |
|
||||
|
||||
Note: `EXISTS` MUST always return `true` for the REQUIRED context attributes
|
||||
because the input CloudEvent is always assumed valid, e.g. `EXISTS id` MUST
|
||||
always return `true`.
|
||||
|
||||
#### 3.4.5. In operator
|
||||
|
||||
| Definition | Semantics |
|
||||
| ------------------------------------------------------- | -------------------------------------------------------------------------- |
|
||||
| `x IN (y1, y2, ...): Any x Any^n -> Boolean`, n > 0 | Returns `true` if `x` is equal to an element in the _Set_ of `yN` elements |
|
||||
| `x NOT IN (y1, y2, ...): Any x Any^n -> Boolean`, n > 0 | Same as `NOT (x IN set)` |
|
||||
|
||||
The matching is done using the same semantics of the equal `=` operator, but
|
||||
using `x` type as the target type for the implicit type casting.
|
||||
|
||||
### 3.5. Functions
|
||||
|
||||
CESQL provides the concept of function, and defines some built-in functions
|
||||
that every engine MUST implement. An engine SHOULD also allow users to define
|
||||
their custom functions, however, the mechanism by which this is done is out of
|
||||
scope of this specification.
|
||||
|
||||
A function is identified by its name, its parameters and the return value. A
|
||||
function can be variadic, that is, the arity is not fixed.
|
||||
|
||||
CESQL allows overloading, that is, the engine MUST be able to distinguish
|
||||
between two functions defined with the same name but different arity. Because
|
||||
of implicit casting, no functions with the same name and same arity but
|
||||
different types are allowed.
|
||||
|
||||
A function name MAY have at most one variadic overload definition and only if
|
||||
the number of initial fixed arguments is greater than the maximum arity of all
|
||||
other function definitions for that function name.
|
||||
|
||||
For example, the following set of definitions are valid and will all be allowed
|
||||
by the rules:
|
||||
|
||||
- `ABC(x): String -> Integer`: Unary function (arity 1).
|
||||
- `ABC(x, y): String x String -> Integer`: Binary function (arity 2).
|
||||
- `ABC(x, y, z, ...): String x String x String x String^n -> Integer`: n-ary
|
||||
function (variable arity), but the initial fixed arguments are at least 3.
|
||||
|
||||
But the following set is invalid, so the engine MUST reject them:
|
||||
|
||||
- `ABC(x...): String^n -> Integer`: n-ary function (variable arity), but there
|
||||
are no initial fixed arguments.
|
||||
- `ABC(x, y, z): String x String x String -> Integer`: Ternary function
|
||||
(arity 3).
|
||||
|
||||
These two are incompatible because the n-ary function `ABC(x...)` can not be
|
||||
distinguished in any way from the ternary function `ABC(x, y, z)` if the n-ary
|
||||
function were called with three arguments. In order for these definitions to be
|
||||
valid, the n-ary function would need to have at least 4 fixed arguments.
|
||||
|
||||
When a function invocation cannot be dispatched, the return value is `false`,
|
||||
and a _MissingFunctionError_ is also returned.
|
||||
|
||||
The following tables show the built-in functions that MUST be supported by a
|
||||
CESQL evaluator.
|
||||
|
||||
#### 3.5.1. Built-in String manipulation
|
||||
|
||||
| Definition | Semantics |
|
||||
| ------------------------------------------------------------------------ | -------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
|
||||
| `LENGTH(x): String -> Integer` | Returns the character length of the String `x`. |
|
||||
| `CONCAT(x1, x2, ...): String^n -> String`, n >= 0 | Returns the concatenation of `x1` up to `xN`. |
|
||||
| `CONCAT_WS(delimiter, x1, x2, ...): String x String^n -> String`, n >= 0 | Returns the concatenation of `x1` up to `xN`, using the `delimiter` between each string, but not before `x1` or after `xN`. |
|
||||
| `LOWER(x): String -> String` | Returns `x` in lowercase. |
|
||||
| `UPPER(x): String -> String` | Returns `x` in uppercase. |
|
||||
| `TRIM(x): String -> String` | Returns `x` with leading and trailing whitespaces (as defined by unicode) trimmed. This does not remove any characters which are not unicode whitespace characters, such as control characters. |
|
||||
| `LEFT(x, y): String x Integer -> String` | Returns a new string with the first `y` characters of `x`, or returns `x` if `LENGTH(x) <= y`. Returns `x` if `y < 0` and a _FunctionEvaluationError_. |
|
||||
| `RIGHT(x, y): String x Integer -> String` | Returns a new string with the last `y` characters of `x` or returns `x` if `LENGTH(x) <= y`. Returns `x` if `y < 0` and a _FunctionEvaluationError_. |
|
||||
| `SUBSTRING(x, pos): String x Integer x Integer -> String` | Returns the substring of `x` starting from index `pos` (included) up to the end of `x`. Characters' index starts from `1`. If `pos` is negative, the beginning of the substring is `pos` characters from the end of the string. If `pos` is 0, then returns the empty string. Returns the empty string and a _FunctionEvaluationError_ if `pos > LENGTH(x) OR pos < -LENGTH(x)`. |
|
||||
| `SUBSTRING(x, pos, len): String x Integer x Integer -> String` | Returns the substring of `x` starting from index `pos` (included) of length `len`. Characters' index starts from `1`. If `pos` is negative, the beginning of the substring is `pos` characters from the end of the string. If `pos` is 0, then returns the empty string. If `len` is greater than the maximum substring starting at `pos`, then return the maximum substring. Returns the empty string and a _FunctionEvaluationError_ if `pos > LENGTH(x) OR pos < -LENGTH(x)` or if `len` is negative. |
|
||||
|
||||
#### 3.5.2. Built-in Math functions
|
||||
|
||||
| Definition | Semantics |
|
||||
| ---------------------------- | ----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
|
||||
| `ABS(x): Integer -> Integer` | Returns the absolute value of `x`. If the value of `x` is `-2147483648` (the most negative 32 bit integer value possible), then this returns `2147483647` as well as a _MathError_. |
|
||||
|
||||
#### 3.5.3 Function Errors
|
||||
|
||||
As specified in 3.3, in the event of an error a function MUST still return a
|
||||
valid return value for its defined return type. A CESQL engine MUST guarantee
|
||||
that all built-in functions comply with this. For user defined functions, if
|
||||
they return one or more errors and fail to provide a valid return value for
|
||||
their return type the CESQL engine MUST return the zero value for the return
|
||||
type of the function, along with a _FunctionEvaluationError_.
|
||||
|
||||
### 3.6. Evaluation of the expression
|
||||
|
||||
Operators and functions MUST be evaluated in order of precedence, and MUST be
|
||||
evaluated left to right when the precedence is equal. The order of precedence
|
||||
is as follows:
|
||||
|
||||
1. Function invocations
|
||||
1. Unary operators
|
||||
1. NOT unary operator
|
||||
1. `-` unary operator
|
||||
1. LIKE operator
|
||||
1. EXISTS operator
|
||||
1. IN operator
|
||||
1. Binary operators
|
||||
1. `*`, `/`, `%` binary operators
|
||||
1. `+`, `-` binary operators
|
||||
1. `=`, `!=`, `<>`, `>=`, `<=`, `>`, `<` binary operators
|
||||
1. AND, OR, XOR binary operators
|
||||
1. Subexpressions
|
||||
1. Attributes and literal values
|
||||
|
||||
AND and OR operations MUST be short-circuit evaluated. When the left operand of
|
||||
the AND operation evaluates to `false`, the right operand MUST NOT be evaluated.
|
||||
Similarly, when the left operand of the OR operation evalues to `true`, the
|
||||
right operand MUST NOT be evaluated.
|
||||
|
||||
#### 3.7. Type casting
|
||||
|
||||
The following table indicates which type casts a CESQL engine MUST or MUST NOT
|
||||
support:
|
||||
|
||||
| Type | Integer | String | Boolean |
|
||||
| ------- | ------- | ------ | ------- |
|
||||
| Integer | N/A | MUST | MUST |
|
||||
| String | MUST | N/A | MUST |
|
||||
| Boolean | MUST | MUST | N/A |
|
||||
|
||||
For all of the type casts which a CESQL engine MUST support, the semantics
|
||||
which the engine MUST use are defined as follows:
|
||||
|
||||
| Definition | Semantics |
|
||||
| -------------------- | ------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------ |
|
||||
| `Integer -> String` | Returns the string representation of the integer value in base 10, without leading `0`s. If the value is less than 0, the '-' character is prepended to the result. |
|
||||
| `Integer -> Boolean` | Returns `false` if the integer is `0`, and `true` otherwise. |
|
||||
| `String -> Integer` | Returns the result of interpreting the string as a 32 bit base 10 integer. The string MAY begin with a leading sign '+' or '-'. If the result will overflow or the string is not a valid integer an error is returned along with a value of `0`. |
|
||||
| `String -> Boolean` | Returns `true` or `false` if the lower case representation of the string is exactly "true" or "false, respectively. Otherwise returns an error along with a value of `false` |
|
||||
| `Boolean -> Integer` | Returns `1` if the boolean is `true`, and `0` if the boolean is `false`. |
|
||||
| `Boolean -> String` | Returns `"true"` if the boolean is `true`, and `"false"` if the boolean is `false`. |
|
||||
|
||||
An example of how _Boolean_ values cast to _String_ combines with the case
|
||||
insensitivity of CESQL keywords is that:
|
||||
|
||||
```
|
||||
TRUE = "true" AND FALSE = "false"
|
||||
```
|
||||
|
||||
will evaluate to `true`, while
|
||||
|
||||
```
|
||||
TRUE = "TRUE" OR FALSE = "FALSE"
|
||||
```
|
||||
|
||||
will evaluate to `false`.
|
||||
|
||||
When the argument types of an operator/function invocation don't match the
|
||||
signature of the operator/function being invoked, the CESQL engine MUST try to
|
||||
perform an implicit cast.
|
||||
|
||||
This section defines an **ambiguous** operator as an operator that is
|
||||
overloaded with another operator definition with same symbol/name and arity but
|
||||
different parameter types. Note: a function can not be ambiguous as it is not
|
||||
allowed for two functions to have the same arity and name.
|
||||
|
||||
A CESQL engine MUST apply the following implicit casting rules in order:
|
||||
|
||||
1. If the operator/function is unary (argument `x`):
|
||||
1. If it's not ambiguous, cast `x` to the parameter type.
|
||||
1. If it's ambiguous, raise a _CastError_ and the cast result is `false`.
|
||||
1. If the operator is binary (left operand `x` and right operand `y`):
|
||||
1. If it's not ambiguous, cast `x` and `y` to the corresponding parameter
|
||||
types.
|
||||
1. If it's ambiguous, use the `y` type to search, in the set of ambiguous
|
||||
operators, every definition of the operator using the `y` type as the
|
||||
right parameter type:
|
||||
1. If such operator definition exists and is unique, cast `x` to the type
|
||||
of the left parameter
|
||||
1. Otherwise, raise a _CastError_ and the result is `false`
|
||||
1. If the function is n-ary with `n > 1`:
|
||||
1. Cast all the arguments to the corresponding parameter types.
|
||||
1. If the operator is n-ary with `n > 2`:
|
||||
1. If it's not ambiguous, cast all the operands to the target type.
|
||||
1. If it's ambiguous, raise a _CastError_ and the cast result is `false`.
|
||||
|
||||
For the `IN` operator, a special rule is defined: the left argument MUST be
|
||||
used as the target type to eventually cast the set elements.
|
||||
|
||||
For example, assuming `MY_STRING_PREDICATE` is a unary predicate accepting a
|
||||
_String_ parameter and returning a _Boolean_, this expression:
|
||||
|
||||
```
|
||||
MY_STRING_PREDICATE(sequence + 10)
|
||||
```
|
||||
|
||||
MUST be evaluated as follows:
|
||||
|
||||
1. `sequence` is cast to _Integer_ using the same semantics of `INT`
|
||||
1. `sequence + 10` is executed
|
||||
1. `sequence + 10` result is cast to _String_ using the same semantics of
|
||||
`STRING`
|
||||
1. `MY_STRING_PREDICATE` is invoked with the result of the previous point as
|
||||
input.
|
||||
|
||||
Another example, in this expression `sequence` is cast to _Integer_:
|
||||
|
||||
```
|
||||
sequence = 10
|
||||
```
|
||||
|
||||
`=` is an arity-2 ambiguous operator, because it's defined for
|
||||
`String x String`, `Boolean x Boolean` and `Integer x Integer`. Because the
|
||||
right operand of the operator is an _Integer_ and there is only one `=`
|
||||
definition which uses the type _Integer_ as the right parameter, `sequence`
|
||||
is cast to _Integer_.
|
||||
|
||||
## 4. Implementation suggestions
|
||||
|
||||
This section is meant to provide some suggestions while implementing and
|
||||
adopting the CloudEvents Expression Language. It's non-normative, hence none of
|
||||
the below text is mandatory.
|
||||
|
||||
### 4.1. Error handling
|
||||
|
||||
Because CESQL expressions are total, they always define a return value,
|
||||
included in the [type system](#31-type-system), even after an error occurs.
|
||||
|
||||
When evaluating an expression, the evaluator can operate in two _modes_, in
|
||||
relation to error handling:
|
||||
|
||||
- Fail fast mode: When an error is triggered, the evaluation is interrupted and
|
||||
returns the error, with the zero value for the return type of the expression.
|
||||
- Complete evaluation mode: When an error is triggered, the evaluation is
|
||||
continued, and the evaluation of the expression returns both the result and
|
||||
the error(s).
|
||||
|
||||
Choosing which evaluation mode to adopt and implement depends on the use case.
|
||||
|
||||
## 5. Examples
|
||||
|
||||
_CloudEvent including a subject_
|
||||
|
||||
```
|
||||
EXISTS subject
|
||||
```
|
||||
|
||||
_CloudEvent including the extension 'firstname' with value 'Francesco'_
|
||||
|
||||
```
|
||||
firstname = 'Francesco'
|
||||
```
|
||||
|
||||
_CloudEvent including the extension 'firstname' with value 'Francesco' or the
|
||||
subject with value 'Francesco'_
|
||||
|
||||
```
|
||||
firstname = 'Francesco' OR subject = 'Francesco'
|
||||
```
|
||||
|
||||
_CloudEvent including the extension 'firstname' with value 'Francesco' and
|
||||
extension 'lastname' with value 'Guardiani', or the subject with value
|
||||
'Francesco Guardiani'_
|
||||
|
||||
```
|
||||
(firstname = 'Francesco' AND lastname = 'Guardiani') OR subject = 'Francesco Guardiani'
|
||||
```
|
||||
|
||||
_CloudEvent including the extension 'sequence' with numeric value 10_
|
||||
|
||||
```
|
||||
sequence = 10
|
||||
```
|
||||
|
||||
_CloudEvent including the extension 'hop' and 'ttl', where 'hop' is smaller
|
||||
than 'ttl'_
|
||||
|
||||
```
|
||||
hop < ttl
|
||||
```
|
||||
|
||||
## 6. References
|
||||
|
||||
- [RFC2119][rfc2119] Key words for use in RFCs to Indicate Requirement Levels
|
||||
|
||||
[rfc2119]: https://tools.ietf.org/html/rfc2119
|
||||
[total-programming-language-wiki]: https://en.wikipedia.org/wiki/Total_functional_programming
|
||||
[referential-transparency-wiki]: https://en.wikipedia.org/wiki/Referential_transparency
|
||||
[ce-attribute-naming-convention]: ../cloudevents/spec.md#naming-conventions
|
||||
[ce-type-system]: ../cloudevents/spec.md#type-system
|
||||
[ce-id-attribute]: ../cloudevents/spec.md#id
|
||||
[subscriptions-filter-dialect]: ../subscriptions/spec.md#3241-filter-dialects
|
||||
[ebnf-xml-spec]: https://www.w3.org/TR/REC-xml/#sec-notation
|
||||
[modulo-operation-wiki]: https://en.wikipedia.org/wiki/Modulo_operation
|
||||
[iso-9075]: https://en.wikipedia.org/wiki/ISO/IEC_9075
|
||||
|
|
@ -0,0 +1,3 @@
|
|||
# CloudEvents - Version 1.0.3-wip
|
||||
|
||||
See the [CloudEvents specification](spec.md).
|
|
@ -0,0 +1,160 @@
|
|||
# CloudEvents Release Notes
|
||||
|
||||
<!-- no verify-specs -->
|
||||
|
||||
## v1.0.2 - 2022/02/05
|
||||
- Add C# namespace option to proto (#937)
|
||||
- Tweak SDK requirements wording (#915)
|
||||
- Re-organized repo directory structure (#904/#905)
|
||||
- Translate CE specs into Chinese (#899/#898)
|
||||
- Explicitly state application/json defaulting when serializing (#881)
|
||||
- Add PowerShell SDK to the list of SDKs (#875)
|
||||
- WebHook "Origin" header concept clashes with RFC6454 (#870)
|
||||
- Clarify data encoding in JSON format with a JSON datacontenttype (#861)
|
||||
- Webhook-Allowed-Origin instead of Webhook-Request-Origin (#836)
|
||||
- Clean-up of Sampled Rate Extension (#832)
|
||||
- Remove the conflicting sentence in Kafka Binding (#823/#813)
|
||||
- Fix the sentences conflict in Kafka Binding (#814)
|
||||
- Clarify HTTP header value encoding and decoding requirements (#793)
|
||||
- Expand versioning suggestions in Primer (#799)
|
||||
- Add support for protobuf batch format (#801)
|
||||
- Clarify HTTP header value encoding and decoding requirements (#816)
|
||||
- Primer guidance for dealing with errors (#763)
|
||||
- Information Classification Extension (#785)
|
||||
- Clarify the role of partitioning extension in Kafka (#727)
|
||||
|
||||
## v1.0.1 - 2020/12/12
|
||||
- Add protobuf format as a sub-protocol (#721)
|
||||
- Allow JSON values to be null, meaning unset (#713)
|
||||
- [Primer] Adding a Non-Goal w.r.t Security (#712)
|
||||
- WebSockets protocol binding (#697)
|
||||
- Clarify difference between message mode and HTTP content mode (#672)
|
||||
- add missing sdks to readme (#666)
|
||||
- New sdk maintainers rules (#665)
|
||||
- move sdk governance and cleanup (#663)
|
||||
- Bring 'datadef' definition into line with specification (#658)
|
||||
- Add CoC and move some governance docs into 'community' (#656)
|
||||
- Add blog post around understanding Cloud Events interactions (#651)
|
||||
- SDK governance draft (#649)
|
||||
- docs: add common processes for SDK maintainers and contributors (#648)
|
||||
- Adding Demo for Cloud Events Orchestration (#646)
|
||||
- Clarified MUST requirement for JSON format (#644)
|
||||
- Re-Introducing Protocol Buffer Representation (#626)
|
||||
- Closes #615 (#616)
|
||||
- Reworked Distributed Tracing Extension (#607)
|
||||
- Minor updates to Cloud Events Primer (#600)
|
||||
- Kafka clarifications (#599)
|
||||
- Proprietary binding spec inclusion guide (#595)
|
||||
- Adding link to Pub/Sub binding (#588)
|
||||
- Add some clarity around SDK milestones (#584)
|
||||
- How to determine binary CE vs random non-CE message (#577)
|
||||
- Adding Visual Studio Code extension to community open-source doc (#573)
|
||||
- Specify encoding of kafka header keys and values and message key (#572)
|
||||
- Fix distributed tracing example (#569)
|
||||
- Paragraph about nested events to the primer (#567)
|
||||
- add rules for changing Admins- #564
|
||||
- Updating JSON Schema (#563)
|
||||
- Say it's ok to ignore non-MUST recommendations - at your own risk (#562)
|
||||
- Update Distributed Tracing extension spec links (#550)
|
||||
- Add Ruby SDK to SDK lists (#548)
|
||||
|
||||
## v1.0.0 - 2019/10/24
|
||||
- Use "producer" and "consumer" instead of "sender" and "receiver"
|
||||
- Clarification that intermediaries should forward optional attributes
|
||||
- Remove constraint that attribute names must start with a letter
|
||||
- Remove suggestion that attributes names should be descriptive and terse
|
||||
- Clarify that a single occurrence may result in more than one event
|
||||
- Add an Event Data section (replacing `data`), making event data a top level
|
||||
concept rather than an attribute
|
||||
- Introduce an Event Format section
|
||||
- Define structured-mode and binary-mode messages
|
||||
- Define protocol binding
|
||||
- Add extension attributes into "context attributes" description
|
||||
- Move mention of attribute serialization mechanism from "context attributes"
|
||||
description into "type system"
|
||||
- Change "transport" to "protocol" universally
|
||||
- Introduce the Boolean, URI and URI-reference types for attributes
|
||||
- Remove the Any and Map types for attributes
|
||||
- Clarify which Unicode characters are permitted in String attributes
|
||||
- Require all context attribute values to be one of the listed types,
|
||||
and state that they may be presented as native types or strings.
|
||||
- Require `source` to be non-empty; recommend an absolute URI
|
||||
- Update version number from 0.3 to 1.0
|
||||
- Clarify that `type` is related to "the originating occurrence"
|
||||
- Remove `datacontentencoding` section
|
||||
- Clarify handling of missing `datacontenttype` attribute
|
||||
- Rename `schemaurl` to `dataschema`, and change type from URI-reference to URI
|
||||
- Constrain `dataschema` to be non-empty (when present)
|
||||
- Add details of how `time` can be generated when it can't be determined,
|
||||
specifically around consistency within a source
|
||||
- Add details of extension context attribute handling
|
||||
- Add recommendation that CloudEvent receivers pass on non-CloudEvent metadata
|
||||
- Sample CloudEvent no longer has a JSON object as a sample extension value
|
||||
|
||||
## v0.3 - 2019/06/13
|
||||
- Update to title format. (#447)
|
||||
- Remove blank section
|
||||
- Misc. typo fixes
|
||||
- Add some guidance on how to construct CloudEvents (#404)
|
||||
- Size Constraints (#405)
|
||||
- Type system changes // canonical string representation (#432)
|
||||
- Add some additional design points for ID (#403)
|
||||
- Add "Subject" context attribute definition
|
||||
- Terminology additions for Source, Consumer, Producer and Intermediary (#420)
|
||||
- Added partitioning extension (#218)
|
||||
- Issue #331: Clarify scope of source and id uniqueness
|
||||
- Added link to dataref.md
|
||||
- Order the attributes section
|
||||
- Fix bad hrefs for our images (#424)
|
||||
- Master represents the future version of the spec, use the future version in the text. (#415)
|
||||
- Adjust examples to include AWS CloudWatch events, our de facto central Event format, and remove valid-but-not-terribly-relevant SNS & Kinesis examples.
|
||||
- Add dataref attribute and describe Claim Check Pattern (#377)
|
||||
- Do some clean-up items for PR 406 that were missed
|
||||
- Introducing "subject" (#406)
|
||||
- Added datacontentencoding (#387)
|
||||
- Add Apache RocketMQ proprietary binding with cloudevents
|
||||
- Ran https://prettier.io/ command on all markdown. (#411)
|
||||
- Privacy & Security (#399)
|
||||
- clarify what OPTIONAL means
|
||||
- Extensions follow attribute naming scheme introduced in #321
|
||||
- add to README
|
||||
- fix typo
|
||||
- The linter can't abide placeholder links 🙄
|
||||
- Collect proprietary specs in dedicated file
|
||||
- Move "extension attributes" section down to end of context attributes
|
||||
- Fixed a broken link in the primer
|
||||
- Fix broken link
|
||||
- Consistency: schemaurl uses URI-reference, protobuf uses URI-reference
|
||||
- HTTP Transport Binding for batching JSON (#370)
|
||||
- minLength for non-empty attributes, add schemaurl (#372)
|
||||
- Fix type reference in it's description
|
||||
- Format data consistently with the paragraph above
|
||||
- remove duplicate paragraph
|
||||
- Add Integer as allowed for Any in description of variant type
|
||||
- s/contenttype/datatype/g
|
||||
- Add an announcement to our release process
|
||||
- Transports are responsible for batching messages (#360)
|
||||
- Specify range of Integer type exactly (#361)
|
||||
- Fix TOC in http transport
|
||||
- add KubeCon demo info
|
||||
|
||||
## v0.2 - 2018/12/06
|
||||
- Added HTTP WebHook Specification (#155)
|
||||
- Added AMQP 1.0 transport and AMQP type system mapping (#157)
|
||||
- Added MQTT 3.1.1 and 5.0 transport binding (#158)
|
||||
- Added NATS transport binding (#215)
|
||||
- Added Distributed Tracing extension (#227)
|
||||
- Added a Primer (#238)
|
||||
- Added Sampling extension (#243)
|
||||
- Defined minimum bar for new protocols/encodings (#254)
|
||||
- Removed eventTypeVersion (#256)
|
||||
- Moved serialization of extensions to be top-level JSON attributes (#277)
|
||||
- Added Sequence extension (#291)
|
||||
- Added Protobuf transport (#295)
|
||||
- Defined minimum bar for new extensions (#308)
|
||||
- Require all attributes to be lowercase and restrict the character set (#321)
|
||||
- Simplified/shortened the attribute names (#339)
|
||||
- Added initial draft of an SDK design doc (#356)
|
||||
|
||||
## v0.1 - 2018/04/20
|
||||
- First draft release of the spec!
|
|
@ -0,0 +1,229 @@
|
|||
# CloudEvents SDK Requirements
|
||||
|
||||
<!-- no verify-specs -->
|
||||
|
||||
The intent of this document to describe a minimum set of requirements for new
|
||||
Software Development Kits (SDKs) for CloudEvents. These SDKs are designed and
|
||||
implemented to enhance and speed up CloudEvents integration. As part of
|
||||
community efforts CloudEvents team committed to support and maintain the
|
||||
following SDKs:
|
||||
|
||||
- [C#/.NET SDK](https://github.com/cloudevents/sdk-csharp)
|
||||
- [Go SDK](https://github.com/cloudevents/sdk-go)
|
||||
- [Java SDK](https://github.com/cloudevents/sdk-java)
|
||||
- [JavaScript SDK](https://github.com/cloudevents/sdk-javascript)
|
||||
- [PHP SDK](https://github.com/cloudevents/sdk-php)
|
||||
- [PowerShell SDK](https://github.com/cloudevents/sdk-powershell)
|
||||
- [Python SDK](https://github.com/cloudevents/sdk-python)
|
||||
- [Ruby SDK](https://github.com/cloudevents/sdk-ruby)
|
||||
- [Rust SDK](https://github.com/cloudevents/sdk-rust)
|
||||
|
||||
This is intended to provide guidance and requirements for SDK authors. This
|
||||
document is intended to be kept up to date with the CloudEvents spec.
|
||||
|
||||
The SDKs are community driven activities and are (somewhat) distinct from the
|
||||
CloudEvents specification itself. In other words, while ideally the SDKs are
|
||||
expected to keep up with changes to the specification, it is not a hard
|
||||
requirement that they do so. It will be continguent on the specific SDK's
|
||||
maintainers to find the time.
|
||||
|
||||
## Contribution Acceptance
|
||||
|
||||
Being an open source community the CloudEvents team is open for new members as
|
||||
well open to their contributions. In order to ensure that an SDK is going to be
|
||||
supported and maintained the CloudEvents community would like to ensure that:
|
||||
|
||||
- Each SDK has active points of contact.
|
||||
- Each SDK supports the latest(N), and N-1, major releases of the
|
||||
[CloudEvent spec](spec.md)\*.
|
||||
- Within the scope of a major release, only support for the latest minor
|
||||
version is needed.
|
||||
|
||||
Support for release candidates is not required, but strongly encouraged.
|
||||
|
||||
\* Note: v1.0 is a special case and it is recommended that as long as v1.0
|
||||
is the latest version, SDKs should also support v0.3.
|
||||
|
||||
## Technical Requirements
|
||||
|
||||
Each SDK MUST meet these requirements:
|
||||
|
||||
- Supports CloudEvents at spec milestones and ongoing development version.
|
||||
- Encode a canonical Event into a transport specific encoded message.
|
||||
- Decode transport specific encoded messages into a Canonical Event.
|
||||
- Idiomatic usage of the programming language.
|
||||
- Using current language version(s).
|
||||
- Supports HTTP transport renderings in both `structured` and `binary`
|
||||
content mode.
|
||||
|
||||
### Object Model Structure Guidelines
|
||||
|
||||
Each SDK will provide a generic CloudEvents class/object/structure that
|
||||
represents the canonical form of an Event.
|
||||
|
||||
The SDK should enable users to bypass implementing transport specific encoding
|
||||
and decoding of the CloudEvents `Event` object. The general flow for Objects
|
||||
should be:
|
||||
|
||||
```
|
||||
Event (-> Message) -> Transport
|
||||
```
|
||||
|
||||
and
|
||||
|
||||
```
|
||||
Transport (-> Message) -> Event
|
||||
```
|
||||
|
||||
An SDK is not required to implement a wrapper around the transport, the focus
|
||||
should be around allowing programming models to work with the high level `Event`
|
||||
object, and providing tools to take the `Event` and turn it into something that
|
||||
can be used with the implementation transport selected.
|
||||
|
||||
At a high level, the SDK needs to be able to help with the following tasks:
|
||||
|
||||
1. Compose an Event.
|
||||
1. Encode an Event given a transport and encoding (into a Transport Message if
|
||||
appropriate).
|
||||
1. Decode an Event given a transport specific message, request or response (into
|
||||
a Transport Message if appropriate).
|
||||
|
||||
#### Compose an Event
|
||||
|
||||
Provide a convenient way to compose both a single message and many messages.
|
||||
Implementers will need a way to quickly build up and convert their event data
|
||||
into the a CloudEvents encoded Event. In practice there tend to be two aspects
|
||||
to event composition,
|
||||
|
||||
1. Event Creation
|
||||
|
||||
- "I have this data that is not formatted as a CloudEvent and I want it to be."
|
||||
|
||||
1. Event Mutation
|
||||
|
||||
- "I have a CloudEvents formatted Event and I need it to be a different Event."
|
||||
- "I have a CloudEvents formatted Event and I need to mutate the Event."
|
||||
|
||||
Event creation is highly idiomatic to the SDK language.
|
||||
|
||||
Event mutation tends to be solved with an accessor pattern, like getters and
|
||||
setters. But direct key access could be leveraged, or named-key accessor
|
||||
functions.
|
||||
|
||||
In either case, there MUST be a method for validating the resulting Event object
|
||||
based on the parameters set, most importantly the CloudEvents spec version.
|
||||
|
||||
#### Encode/Decode an Event
|
||||
|
||||
Each SDK MUST support encoding and decoding an Event with regards to a transport
|
||||
and encoding:
|
||||
|
||||
- Each SDK MUST support structured-mode messages for each transport that it
|
||||
supports.
|
||||
- Each SDK SHOULD support binary-mode messages for each transport that it
|
||||
supports.
|
||||
- Each SDK SHOULD support batch-mode messages for each transport that it
|
||||
supports (where the event format and transport combination supports batch mode).
|
||||
- Each SDK SHOULD indicate which modes it supports for each supported event
|
||||
format, both in the [table below](#feature-support) and in any SDK-specific
|
||||
documentation provided.
|
||||
|
||||
Note that when decoding an event, media types MUST be matched
|
||||
case-insensitively, as specified in [RFC 2045]
|
||||
(https://tools.ietf.org/html/rfc2045).
|
||||
|
||||
#### Data
|
||||
|
||||
Data access from the event has some considerations, the Event at rest could be
|
||||
encoded into the `base64` form, as structured data, or as a wire format like
|
||||
`json`. An SDK MUST provide a method for unpacking the data from these formats
|
||||
into a native format.
|
||||
|
||||
#### Extensions
|
||||
|
||||
Supporting CloudEvents extensions is idiomatic again, but a method that mirrors
|
||||
the data access seems to work.
|
||||
|
||||
#### Validation
|
||||
|
||||
Validation MUST be possible on an individual Event. Validation MUST take into
|
||||
account the spec version, and all the requirements put in-place by the spec at
|
||||
each version.
|
||||
|
||||
SDKs SHOULD perform validation on context attribute values provided to it by
|
||||
the SDK user. This will help ensure that only valid CloudEvents are generated.
|
||||
|
||||
## Documentation
|
||||
|
||||
Each SDK must provide examples using at least HTTP transport of:
|
||||
|
||||
- Composing an Event.
|
||||
- Encoding and sending a composed Event.
|
||||
- Receiving and decoding an Event.
|
||||
|
||||
## Feature Support
|
||||
|
||||
Each SDK must update the following "support table" periodically to ensure
|
||||
they accurately the status of each SDK's support for the stated features.
|
||||
|
||||
<!--
|
||||
Do these commands in vi with the cursor after these comments.
|
||||
|
||||
Easiest to edit table by first doing this:
|
||||
:g/^|/s/ :heavy_check_mark: / :y: /g
|
||||
and making the window wide enough that lines don't wrap. Then it should look nice.
|
||||
|
||||
Undo it when done:
|
||||
:g/^|/s/ :y: / :heavy_check_mark: /g
|
||||
-->
|
||||
|
||||
| Feature | C# | Go | Java | JS | PHP | PS | Python | Ruby | Rust |
|
||||
|:----------------------------------------------------------------------------------------------------------------------------------------------| :-: | :-: | :--: | :-: | :-: | :-: | :----: | :--: | :--: |
|
||||
| **[v1.0](https://github.com/cloudevents/spec/tree/v1.0)** |
|
||||
| [CloudEvents Core](https://github.com/cloudevents/spec/blob/v1.0.2/cloudevents/spec.md) | :heavy_check_mark: | :heavy_check_mark: | :heavy_check_mark: | :heavy_check_mark: | :heavy_check_mark: | :heavy_check_mark: | :heavy_check_mark: | :heavy_check_mark: | :heavy_check_mark: |
|
||||
| Event Formats |
|
||||
| [Avro](https://github.com/cloudevents/spec/blob/v1.0.2/cloudevents/formats/avro-format.md) | :heavy_check_mark: | | :x: | :x: | | | | :x: | :x: |
|
||||
| [Avro Compact](https://github.com/cloudevents/spec/blob/main/cloudevents/working-drafts/avro-compact-format.md) | :heavy_check_mark: | | :x: | :x: | | | | | :x: |
|
||||
| [JSON](https://github.com/cloudevents/spec/blob/v1.0.2/cloudevents/formats/json-format.md) | :heavy_check_mark: | | :heavy_check_mark: | :heavy_check_mark: | | | :heavy_check_mark: | :heavy_check_mark: | :heavy_check_mark: |
|
||||
| [Protobuf ](https://github.com/cloudevents/spec/blob/v1.0.2/cloudevents/formats/protobuf-format.md) | :heavy_check_mark: | | :heavy_check_mark: | :x: | | | | :x: | :x: |
|
||||
| Bindings / Content Modes |
|
||||
| [AMQP Binary](https://github.com/cloudevents/spec/blob/v1.0.2/cloudevents/bindings/amqp-protocol-binding.md#31-binary-content-mode) | :heavy_check_mark: | | :heavy_check_mark: | :x: | | | | :x: | :x: |
|
||||
| [AMQP Structured](https://github.com/cloudevents/spec/blob/v1.0.2/cloudevents/bindings/amqp-protocol-binding.md#32-structured-content-mode) | :heavy_check_mark: | | :heavy_check_mark: | :x: | | | | :x: | :x: |
|
||||
| [HTTP Binary](https://github.com/cloudevents/spec/blob/v1.0.2/cloudevents/bindings/http-protocol-binding.md#31-binary-content-mode) | :heavy_check_mark: | | :heavy_check_mark: | :heavy_check_mark: | | | :heavy_check_mark: | :heavy_check_mark: | :heavy_check_mark: |
|
||||
| [HTTP Structured](https://github.com/cloudevents/spec/blob/v1.0.2/cloudevents/bindings/http-protocol-binding.md#32-structured-content-mode) | :heavy_check_mark: | | :heavy_check_mark: | :heavy_check_mark: | | | :heavy_check_mark: | :heavy_check_mark: | :heavy_check_mark: |
|
||||
| [HTTP Batch](https://github.com/cloudevents/spec/blob/v1.0.2/cloudevents/bindings/http-protocol-binding.md#33-batched-content-mode) | :heavy_check_mark: | | :x: | :x: | | | | :heavy_check_mark: | :heavy_check_mark: |
|
||||
| [Kafka Binary](https://github.com/cloudevents/spec/blob/v1.0.2/cloudevents/bindings/kafka-protocol-binding.md#32-binary-content-mode) | :heavy_check_mark: | | :heavy_check_mark: | :heavy_check_mark: | | | :heavy_check_mark: | :x: | :heavy_check_mark: |
|
||||
| [Kafka Structured](https://github.com/cloudevents/spec/blob/v1.0.2/cloudevents/bindings/kafka-protocol-binding.md#33-structured-content-mode) | :heavy_check_mark: | | :heavy_check_mark: | :heavy_check_mark: | | | :heavy_check_mark: | :x: | :heavy_check_mark: |
|
||||
| [MQTT v5 Binary](https://github.com/cloudevents/spec/blob/v1.0.2/cloudevents/bindings/mqtt-protocol-binding.md#31-binary-content-mode) | :x: | | :x: | :heavy_check_mark: | | | | :x: | :x: |
|
||||
| [MQTT Structured](https://github.com/cloudevents/spec/blob/v1.0.2/cloudevents/bindings/mqtt-protocol-binding.md#32-structured-content-mode) | :heavy_check_mark: | | :x: | :heavy_check_mark: | | | | :x: | :x: |
|
||||
| [NATS Binary](https://github.com/cloudevents/spec/blob/v1.0.2/cloudevents/bindings/nats-protocol-binding.md) | :x: | | :x: | :x: | | | | :x: | :heavy_check_mark: |
|
||||
| [NATS Structured](https://github.com/cloudevents/spec/blob/v1.0.2/cloudevents/bindings/nats-protocol-binding.md) | :x: | | :x: | :x: | | | | :x: | :heavy_check_mark: |
|
||||
| [WebSockets Binary](https://github.com/cloudevents/spec/blob/v1.0.2/cloudevents/bindings/websockets-protocol-binding.md) | :x: | | :x: | :heavy_check_mark: | | | | :x: | :x: |
|
||||
| [WebSockets Structured](https://github.com/cloudevents/spec/blob/v1.0.2/cloudevents/bindings/websockets-protocol-binding.md) | :x: | | :x: | :heavy_check_mark: | | | | :x: | :x: |
|
||||
| Proprietary Bindings |
|
||||
| [RocketMQ](https://github.com/apache/rocketmq-externals/blob/master/rocketmq-cloudevents-binding/rocketmq-transport-binding.md) | :x: | | :heavy_check_mark: | :x: | | | | :x: | :x: |
|
||||
| [RabbitMQ](https://github.com/knative-extensions/eventing-rabbitmq/blob/main/cloudevents-protocol-spec/spec.md) | :x: | | | | | | | | |
|
||||
| |
|
||||
| **[v0.3](https://github.com/cloudevents/spec/tree/v0.3)** |
|
||||
| [CloudEvents Core](https://github.com/cloudevents/spec/blob/v0.3/spec.md) | :x: | :heavy_check_mark: | :heavy_check_mark: | :heavy_check_mark: | :x: | :x: | :heavy_check_mark: | :heavy_check_mark: | :heavy_check_mark: |
|
||||
| Event Formats |
|
||||
| [AMQP](https://github.com/cloudevents/spec/blob/v0.3/amqp-format.md) | :x: | | :x: | :x: | | | | :x: | :x: |
|
||||
| [JSON](https://github.com/cloudevents/spec/blob/v0.3/json-format.md) | :x: | | :heavy_check_mark: | :heavy_check_mark: | | | :heavy_check_mark: | :heavy_check_mark: | :heavy_check_mark: |
|
||||
| [Protobuf](https://github.com/cloudevents/spec/blob/v0.3/protobuf-format.md) | :x: | | :heavy_check_mark: | :x: | | | | :x: | :x: |
|
||||
| Bindings / Content Modes |
|
||||
| [AMQP Binary](https://github.com/cloudevents/spec/blob/v0.3/amqp-transport-binding.md#31-binary-content-mode) | :x: | | :heavy_check_mark: | :x: | | | | :x: | :x: |
|
||||
| [AMQP Structured](https://github.com/cloudevents/spec/blob/v0.3/amqp-transport-binding.md#32-structured-content-mode) | :x: | | :heavy_check_mark: | :x: | | | | :x: | :x: |
|
||||
| [HTTP Binary](https://github.com/cloudevents/spec/blob/v0.3/http-transport-binding.md) | :x: | | :heavy_check_mark: | :heavy_check_mark: | | | :heavy_check_mark: | :heavy_check_mark: | :heavy_check_mark: |
|
||||
| [HTTP Structured](https://github.com/cloudevents/spec/blob/v0.3/http-transport-binding.md) | :x: | | :heavy_check_mark: | :heavy_check_mark: | | | :heavy_check_mark: | :heavy_check_mark: | :heavy_check_mark: |
|
||||
| [HTTP Batch](https://github.com/cloudevents/spec/blob/v0.3/http-transport-binding.md) | :x: | | :x: | :x: | | | | :heavy_check_mark: | :heavy_check_mark: |
|
||||
| [Kafka Binary](https://github.com/cloudevents/spec/blob/v1.0.2/cloudevents/bindings/kafka-protocol-binding.md#32-binary-content-mode) | :x: | | :heavy_check_mark: | :heavy_check_mark: | | | :heavy_check_mark: | :x: | :heavy_check_mark: |
|
||||
| [Kafka Structured](https://github.com/cloudevents/spec/blob/v1.0.2/cloudevents/bindings/kafka-protocol-binding.md#33-structured-content-mode) | :x: | | :heavy_check_mark: | :heavy_check_mark: | | | :heavy_check_mark: | :x: | :heavy_check_mark: |
|
||||
| [MQTT v5 Binary](https://github.com/cloudevents/spec/blob/v0.3/mqtt-transport-binding.md) | :x: | | :x: | :x: | | | | :x: | :x: |
|
||||
| [MQTT Structured](https://github.com/cloudevents/spec/blob/v0.3/mqtt-transport-binding.md) | :x: | | :x: | :x: | | | | :x: | :x: |
|
||||
| [NATS Binary](https://github.com/cloudevents/spec/blob/v0.3/nats-transport-binding.md) | :x: | | :x: | :x: | | | | :x: | :heavy_check_mark: |
|
||||
| [NATS Structured](https://github.com/cloudevents/spec/blob/v0.3/nats-transport-binding.md) | :x: | | :x: | :x: | | | | :x: | :heavy_check_mark: |
|
||||
| [WebSockets Binary](https://github.com/cloudevents/spec/blob/v1.0.2/cloudevents/bindings/websockets-protocol-binding.md) | :x: | | :x: | :heavy_check_mark: | | | | :x: | :x: |
|
||||
| [WebSockets Structured](https://github.com/cloudevents/spec/blob/v1.0.2/cloudevents/bindings/websockets-protocol-binding.md) | :x: | | :x: | :heavy_check_mark: | | | | :x: | :x: |
|
||||
| Proprietary Bindings |
|
||||
| [RocketMQ](https://github.com/apache/rocketmq-externals/blob/master/rocketmq-cloudevents-binding/rocketmq-transport-binding.md) | :x: | | :heavy_check_mark: | :x: | | | | :x: | :x: |
|
||||
|
|
@ -1,12 +1,16 @@
|
|||
# CloudEvents Adapters
|
||||
|
||||
<!-- no verify-specs -->
|
||||
|
||||
Not all event producers will produce CloudEvents natively. As a result,
|
||||
some "adapter" might be needed to convert these events into CloudEvents.
|
||||
This will typically mean extracting metadata from the events to be used as
|
||||
CloudEvents attributes. In order to promote interoperability across multiple
|
||||
implementations of these adpaters, the following documents show the proposed
|
||||
implementations of these adapters, the following documents show the proposed
|
||||
algorithms that should be used:
|
||||
|
||||
- [AWS S3](adapters/aws-s3.md)
|
||||
- [GitHub](adapters/github.md)
|
||||
- [GitLab](adapters/gitlab.md)
|
||||
- [AWS S3](./aws-s3.md)
|
||||
- [AWS SNS](./aws-sns.md)
|
||||
- [CouchDB](./couchdb.md)
|
||||
- [GitHub](./github.md)
|
||||
- [GitLab](./gitlab.md)
|
|
@ -26,7 +26,8 @@ Comments:
|
|||
- While the "eventSource" value will always be static (`aws:s3`) when
|
||||
the event is coming from S3, if some other cloud provider is supporting
|
||||
the S3 event format it is expected that this value will not be
|
||||
`aws:s3` for them - it should be something specific to their environment.
|
||||
`aws:s3` for them - it is expected to be something specific to their
|
||||
environment.
|
||||
- Consumers of these events will therefore be able to know if the event
|
||||
is an S3 type of event (regardless of whether it is coming from S3 or
|
||||
an S3-compatible provider) by detecting the `com.amazonaws.s3` prefix
|
|
@ -0,0 +1,53 @@
|
|||
# Amazon Simple Notification Service CloudEvents Adapter
|
||||
|
||||
This document describes how to convert [AWS SNS messages][sns-messages] into CloudEvents.
|
||||
|
||||
Amazon SNS MAY send a subscription confirmation, notification, or unsubscribe confirmation
|
||||
message to your HTTP/HTTPS endpoints.
|
||||
|
||||
Each section below describes how to determine the CloudEvents attributes
|
||||
based on the specified type of SNS messages.
|
||||
|
||||
### Subscription Confirmation
|
||||
|
||||
| CloudEvents Attribute | Value |
|
||||
| :-------------------- | :---------------------------------------------- |
|
||||
| `id` | "x-amz-sns-message-id" value |
|
||||
| `source` | "x-amz-sns-topic-arn" value |
|
||||
| `specversion` | `1.0` |
|
||||
| `type` | `com.amazonaws.sns.` + "x-amz-sns-message-type" value |
|
||||
| `datacontenttype` | `application/json` |
|
||||
| `dataschema` | Omit |
|
||||
| `subject` | Omit |
|
||||
| `time` | "Timestamp" value |
|
||||
| `data` | HTTP payload |
|
||||
|
||||
### Notification
|
||||
|
||||
| CloudEvents Attribute | Value |
|
||||
| :-------------------- | :---------------------------------------------- |
|
||||
| `id` | "x-amz-sns-message-id" value |
|
||||
| `source` | "x-amz-sns-subscription-arn" value |
|
||||
| `specversion` | `1.0` |
|
||||
| `type` | `com.amazonaws.sns.` + "x-amz-sns-message-type" value |
|
||||
| `datacontenttype` | `application/json` |
|
||||
| `dataschema` | Omit |
|
||||
| `subject` | "Subject" value (if present) |
|
||||
| `time` | "Timestamp" value |
|
||||
| `data` | HTTP payload |
|
||||
|
||||
### Unsubscribe Confirmation
|
||||
|
||||
| CloudEvents Attribute | Value |
|
||||
| :-------------------- | :---------------------------------------------- |
|
||||
| `id` | "x-amz-sns-message-id" value |
|
||||
| `source` | "x-amz-sns-subscription-arn" value |
|
||||
| `specversion` | `1.0` |
|
||||
| `type` | `com.amazonaws.sns.` + "x-amz-sns-message-type" value |
|
||||
| `datacontenttype` | `application/json` |
|
||||
| `dataschema` | Omit |
|
||||
| `subject` | Omit |
|
||||
| `time` | "Timestamp" value |
|
||||
| `data` | HTTP payload |
|
||||
|
||||
[sns-messages]: https://docs.aws.amazon.com/sns/latest/dg/sns-message-and-json-formats.html
|
|
@ -1,15 +1,47 @@
|
|||
# GitHub CloudEvents Adapter
|
||||
|
||||
This document describes how to convert
|
||||
[GitHub webhook events](https://developer.github.com/v3/activity/events/types/)
|
||||
[GitHub webhook events](https://docs.github.com/en/webhooks/webhook-events-and-payloads)
|
||||
into a CloudEvents.
|
||||
|
||||
GitHub webhook event documentation:
|
||||
https://developer.github.com/v3/activity/events/types/
|
||||
https://docs.github.com/en/webhooks/webhook-events-and-payloads
|
||||
|
||||
Each section below describes how to determine the CloudEvents attributes
|
||||
based on the specified event.
|
||||
|
||||
For time attribute, if the proposed value is null, the default timestamp SHOULD be used.
|
||||
|
||||
### BranchProtectionConfigurationEvent
|
||||
|
||||
| CloudEvents Attribute | Value |
|
||||
| :-------------------- | :------------------------------------------------------------- |
|
||||
| `id` | "X-GitHub-Delivery" HTTP header value |
|
||||
| `source` | "repository.url" value |
|
||||
| `specversion` | `1.0` |
|
||||
| `type` | `com.github.branch_protection_configuration.` + "action" value |
|
||||
| `datacontentencoding` | Omit |
|
||||
| `datacontenttype` | `application/json` |
|
||||
| `dataschema` | Omit |
|
||||
| `subject` | Omit |
|
||||
| `time` | Current time |
|
||||
| `data` | Content of HTTP request body |
|
||||
|
||||
### BranchProtectionRuleEvent
|
||||
|
||||
| CloudEvents Attribute | Value |
|
||||
| :-------------------- | :---------------------------------------------------- |
|
||||
| `id` | "X-GitHub-Delivery" HTTP header value |
|
||||
| `source` | "repository.url" value |
|
||||
| `specversion` | `1.0` |
|
||||
| `type` | `com.github.branch_protection_rule.` + "action" value |
|
||||
| `datacontentencoding` | Omit |
|
||||
| `datacontenttype` | `application/json` |
|
||||
| `dataschema` | Omit |
|
||||
| `subject` | "rule.id" value |
|
||||
| `time` | "rule.updated_at" value |
|
||||
| `data` | Content of HTTP request body |
|
||||
|
||||
### CheckRunEvent
|
||||
|
||||
| CloudEvents Attribute | Value |
|
||||
|
@ -40,6 +72,21 @@ based on the specified event.
|
|||
| `time` | "check_suite.updated_at" value |
|
||||
| `data` | Content of HTTP request body |
|
||||
|
||||
### CodeScanningAlertEvent
|
||||
|
||||
| CloudEvents Attribute | Value |
|
||||
| :-------------------- | :------------------------------------------------- |
|
||||
| `id` | "X-GitHub-Delivery" HTTP header value |
|
||||
| `source` | "repository.url" value |
|
||||
| `specversion` | `1.0` |
|
||||
| `type` | `com.github.code_scanning_alert.` + "action" value |
|
||||
| `datacontentencoding` | Omit |
|
||||
| `datacontenttype` | `application/json` |
|
||||
| `dataschema` | Omit |
|
||||
| `subject` | "alert.number" value |
|
||||
| `time` | Current time |
|
||||
| `data` | Content of HTTP request body |
|
||||
|
||||
### CommitCommentEvent
|
||||
|
||||
| CloudEvents Attribute | Value |
|
||||
|
@ -85,6 +132,36 @@ based on the specified event.
|
|||
| `time` | Current time |
|
||||
| `data` | Content of HTTP request body |
|
||||
|
||||
### CustomPropertyEvent
|
||||
|
||||
| CloudEvents Attribute | Value |
|
||||
| :-------------------- | :--------------------------------------------- |
|
||||
| `id` | "X-GitHub-Delivery" HTTP header value |
|
||||
| `source` | "repository.url" value |
|
||||
| `specversion` | `1.0` |
|
||||
| `type` | `com.github.custom_property.` + "action" value |
|
||||
| `datacontentencoding` | Omit |
|
||||
| `datacontenttype` | `application/json` |
|
||||
| `dataschema` | Omit |
|
||||
| `subject` | "definition.property_name" value |
|
||||
| `time` | Current time |
|
||||
| `data` | Content of HTTP request body |
|
||||
|
||||
### CustomPropertyValuesEvent
|
||||
|
||||
| CloudEvents Attribute | Value |
|
||||
| :-------------------- | :---------------------------------------------------- |
|
||||
| `id` | "X-GitHub-Delivery" HTTP header value |
|
||||
| `source` | "repository.url" value |
|
||||
| `specversion` | `1.0` |
|
||||
| `type` | `com.github.custom_property_values.` + "action" value |
|
||||
| `datacontentencoding` | Omit |
|
||||
| `datacontenttype` | `application/json` |
|
||||
| `dataschema` | Omit |
|
||||
| `subject` | Omit |
|
||||
| `time` | Current time |
|
||||
| `data` | Content of HTTP request body |
|
||||
|
||||
### DeleteEvent
|
||||
|
||||
| CloudEvents Attribute | Value |
|
||||
|
@ -100,6 +177,21 @@ based on the specified event.
|
|||
| `time` | Current time |
|
||||
| `data` | Content of HTTP request body |
|
||||
|
||||
### DependabotAlertEvent
|
||||
|
||||
| CloudEvents Attribute | Value |
|
||||
| :-------------------- | :---------------------------------------------- |
|
||||
| `id` | "X-GitHub-Delivery" HTTP header value |
|
||||
| `source` | "repository.url" value |
|
||||
| `specversion` | `1.0` |
|
||||
| `type` | `com.github.dependabot_alert.` + "action" value |
|
||||
| `datacontentencoding` | Omit |
|
||||
| `datacontenttype` | `application/json` |
|
||||
| `dataschema` | Omit |
|
||||
| `subject` | "alert.id" value |
|
||||
| `time` | Current time |
|
||||
| `data` | Content of HTTP request body |
|
||||
|
||||
### DeployKeyEvent
|
||||
|
||||
| CloudEvents Attribute | Value |
|
||||
|
@ -130,6 +222,36 @@ based on the specified event.
|
|||
| `time` | "deployment.updated_at" value |
|
||||
| `data` | Content of HTTP request body |
|
||||
|
||||
### DeploymentProtectionRuleEvent
|
||||
|
||||
| CloudEvents Attribute | Value |
|
||||
| :-------------------- | :-------------------------------------------------------- |
|
||||
| `id` | "X-GitHub-Delivery" HTTP header value |
|
||||
| `source` | "deployment.url" value |
|
||||
| `specversion` | `1.0` |
|
||||
| `type` | `com.github.deployment_protection_rule.` + "action" value |
|
||||
| `datacontentencoding` | Omit |
|
||||
| `datacontenttype` | `application/json` |
|
||||
| `dataschema` | Omit |
|
||||
| `subject` | "deployment.id" value if exists |
|
||||
| `time` | Current time |
|
||||
| `data` | Content of HTTP request body |
|
||||
|
||||
### DeploymentReviewEvent
|
||||
|
||||
| CloudEvents Attribute | Value |
|
||||
| :-------------------- | :----------------------------------------------- |
|
||||
| `id` | "X-GitHub-Delivery" HTTP header value |
|
||||
| `source` | "deployment.url" value |
|
||||
| `specversion` | `1.0` |
|
||||
| `type` | `com.github.deployment_review.` + "action" value |
|
||||
| `datacontentencoding` | Omit |
|
||||
| `datacontenttype` | `application/json` |
|
||||
| `dataschema` | Omit |
|
||||
| `subject` | "workflow_run.id" value |
|
||||
| `time` | Current time |
|
||||
| `data` | Content of HTTP request body |
|
||||
|
||||
### DeploymentStatusEvent
|
||||
|
||||
| CloudEvents Attribute | Value |
|
||||
|
@ -145,6 +267,36 @@ based on the specified event.
|
|||
| `time` | "deployment_status.updated_at" value |
|
||||
| `data` | Content of HTTP request body |
|
||||
|
||||
### DiscussionEvent
|
||||
|
||||
| CloudEvents Attribute | Value |
|
||||
| :-------------------- | :---------------------------------------- |
|
||||
| `id` | "X-GitHub-Delivery" HTTP header value |
|
||||
| `source` | "repository.url" value |
|
||||
| `specversion` | `1.0` |
|
||||
| `type` | `com.github.discussion.` + "action" value |
|
||||
| `datacontentencoding` | Omit |
|
||||
| `datacontenttype` | `application/json` |
|
||||
| `dataschema` | "discussion.updated_at" value |
|
||||
| `subject` | "discussion.id" value |
|
||||
| `time` | Current time |
|
||||
| `data` | Content of HTTP request body |
|
||||
|
||||
### DiscussionCommentEvent
|
||||
|
||||
| CloudEvents Attribute | Value |
|
||||
| :-------------------- | :------------------------------------------------ |
|
||||
| `id` | "X-GitHub-Delivery" HTTP header value |
|
||||
| `source` | "repository.url" value |
|
||||
| `specversion` | `1.0` |
|
||||
| `type` | `com.github.discussion_comment.` + "action" value |
|
||||
| `datacontentencoding` | Omit |
|
||||
| `datacontenttype` | `application/json` |
|
||||
| `dataschema` | Omit |
|
||||
| `subject` | "discussion.id" value |
|
||||
| `time` | "comment.updated_at" value |
|
||||
| `data` | Content of HTTP request body |
|
||||
|
||||
### ForkEvent
|
||||
|
||||
| CloudEvents Attribute | Value |
|
||||
|
@ -177,18 +329,18 @@ based on the specified event.
|
|||
|
||||
### GollumEvent
|
||||
|
||||
| CloudEvents Attribute | Value |
|
||||
| :-------------------- | :------------------------------------------ |
|
||||
| `id` | "X-GitHub-Delivery" HTTP header value |
|
||||
| `source` | "repository.url" value |
|
||||
| `specversion` | `1.0` |
|
||||
| `type` | `com.github.gollum.` + "pages.action" value |
|
||||
| `datacontentencoding` | Omit |
|
||||
| `datacontenttype` | `application/json` |
|
||||
| `dataschema` | Omit |
|
||||
| `subject` | "pages.page_name" value |
|
||||
| `time` | Current time |
|
||||
| `data` | Content of HTTP request body |
|
||||
| CloudEvents Attribute | Value |
|
||||
| :-------------------- | :------------------------------------ |
|
||||
| `id` | "X-GitHub-Delivery" HTTP header value |
|
||||
| `source` | "repository.url" value |
|
||||
| `specversion` | `1.0` |
|
||||
| `type` | `com.github.gollum` |
|
||||
| `datacontentencoding` | Omit |
|
||||
| `datacontenttype` | `application/json` |
|
||||
| `dataschema` | Omit |
|
||||
| `subject` | Omit |
|
||||
| `time` | Current time |
|
||||
| `data` | Content of HTTP request body |
|
||||
|
||||
### InstallationEvent
|
||||
|
||||
|
@ -207,18 +359,33 @@ based on the specified event.
|
|||
|
||||
### InstallationRepositoryEvent
|
||||
|
||||
| CloudEvents Attribute | Value |
|
||||
| :-------------------- | :----------------------------------------------------- |
|
||||
| `id` | "X-GitHub-Delivery" HTTP header value |
|
||||
| `source` | "installation.account.url" value |
|
||||
| `specversion` | `1.0` |
|
||||
| `type` | `com.github.installation_repository.` + "action" value |
|
||||
| `datacontentencoding` | Omit |
|
||||
| `datacontenttype` | `application/json` |
|
||||
| `dataschema` | Omit |
|
||||
| `subject` | "installation.id" value |
|
||||
| `time` | "installation.updated_at" value # not a timestamp?? |
|
||||
| `data` | Content of HTTP request body |
|
||||
| CloudEvents Attribute | Value |
|
||||
| :-------------------- | :------------------------------------------------------- |
|
||||
| `id` | "X-GitHub-Delivery" HTTP header value |
|
||||
| `source` | "installation.account.url" value |
|
||||
| `specversion` | `1.0` |
|
||||
| `type` | `com.github.installation_repositories.` + "action" value |
|
||||
| `datacontentencoding` | Omit |
|
||||
| `datacontenttype` | `application/json` |
|
||||
| `dataschema` | Omit |
|
||||
| `subject` | "installation.id" value |
|
||||
| `time` | "installation.updated_at" value |
|
||||
| `data` | Content of HTTP request body |
|
||||
|
||||
### InstallationTargetEvent
|
||||
|
||||
| CloudEvents Attribute | Value |
|
||||
| :-------------------- | :------------------------------------------------- |
|
||||
| `id` | "X-GitHub-Delivery" HTTP header value |
|
||||
| `source` | "installation.account.url" value |
|
||||
| `specversion` | `1.0` |
|
||||
| `type` | `com.github.installation_target.` + "action" value |
|
||||
| `datacontentencoding` | Omit |
|
||||
| `datacontenttype` | `application/json` |
|
||||
| `dataschema` | Omit |
|
||||
| `subject` | "installation.id" value |
|
||||
| `time` | Current time |
|
||||
| `data` | Content of HTTP request body |
|
||||
|
||||
### IssueCommentEvent
|
||||
|
||||
|
@ -242,7 +409,7 @@ based on the specified event.
|
|||
| `id` | "X-GitHub-Delivery" HTTP header value |
|
||||
| `source` | "repository.url" value |
|
||||
| `specversion` | `1.0` |
|
||||
| `type` | `com.github.issue.` + "action" value |
|
||||
| `type` | `com.github.issues.` + "action" value |
|
||||
| `datacontentencoding` | Omit |
|
||||
| `datacontenttype` | `application/json` |
|
||||
| `dataschema` | Omit |
|
||||
|
@ -310,6 +477,21 @@ based on the specified event.
|
|||
| `time` | Current time |
|
||||
| `data` | Content of HTTP request body |
|
||||
|
||||
### MergeGroupEvent
|
||||
|
||||
| CloudEvents Attribute | Value |
|
||||
| :-------------------- | :----------------------------------------- |
|
||||
| `id` | "X-GitHub-Delivery" HTTP header value |
|
||||
| `source` | "repository.url" value |
|
||||
| `specversion` | `1.0` |
|
||||
| `type` | `com.github.merge_group.` + "action" value |
|
||||
| `datacontentencoding` | Omit |
|
||||
| `datacontenttype` | `application/json` |
|
||||
| `dataschema` | Omit |
|
||||
| `subject` | "merge_group.head_ref" value |
|
||||
| `time` | Current time |
|
||||
| `data` | Content of HTTP request body |
|
||||
|
||||
### MetaEvent
|
||||
|
||||
| CloudEvents Attribute | Value |
|
||||
|
@ -370,6 +552,21 @@ based on the specified event.
|
|||
| `time` | Current time |
|
||||
| `data` | Content of HTTP request body |
|
||||
|
||||
### PackageEvent
|
||||
|
||||
| CloudEvents Attribute | Value |
|
||||
| :-------------------- | :------------------------------------------------------------------------- |
|
||||
| `id` | "X-GitHub-Delivery" HTTP header value |
|
||||
| `source` | "repository.url" value |
|
||||
| `specversion` | `1.0` |
|
||||
| `type` | `com.github.package.` + "action" value |
|
||||
| `datacontentencoding` | Omit |
|
||||
| `datacontenttype` | `application/json` |
|
||||
| `dataschema` | Omit |
|
||||
| `subject` | "package.id" value |
|
||||
| `time` | "package.updated_at" value, unless "null", then "package.created_at" value |
|
||||
| `data` | Content of HTTP request body |
|
||||
|
||||
### PageBuildEvent
|
||||
|
||||
| CloudEvents Attribute | Value |
|
||||
|
@ -430,6 +627,51 @@ based on the specified event.
|
|||
| `time` | "project.updated_at" value |
|
||||
| `data` | Content of HTTP request body |
|
||||
|
||||
### ProjectsV2Event
|
||||
|
||||
| CloudEvents Attribute | Value |
|
||||
| :-------------------- | :----------------------------------------- |
|
||||
| `id` | "X-GitHub-Delivery" HTTP header value |
|
||||
| `source` | "repository.url" value |
|
||||
| `specversion` | `1.0` |
|
||||
| `type` | `com.github.projects_v2.` + "action" value |
|
||||
| `datacontentencoding` | Omit |
|
||||
| `datacontenttype` | `application/json` |
|
||||
| `dataschema` | Omit |
|
||||
| `subject` | "projects_v2.id" value |
|
||||
| `time` | "projects_v2.updated_at" value |
|
||||
| `data` | Content of HTTP request body |
|
||||
|
||||
### ProjectsV2ItemEvent
|
||||
|
||||
| CloudEvents Attribute | Value |
|
||||
| :-------------------- | :---------------------------------------------- |
|
||||
| `id` | "X-GitHub-Delivery" HTTP header value |
|
||||
| `source` | "repository.url" value |
|
||||
| `specversion` | `1.0` |
|
||||
| `type` | `com.github.projects_v2_item.` + "action" value |
|
||||
| `datacontentencoding` | Omit |
|
||||
| `datacontenttype` | `application/json` |
|
||||
| `dataschema` | Omit |
|
||||
| `subject` | "projects_v2_item.id" value |
|
||||
| `time` | "projects_v2_item.updated_at" value |
|
||||
| `data` | Content of HTTP request body |
|
||||
|
||||
### ProjectsV2StatusUpdateEvent
|
||||
|
||||
| CloudEvents Attribute | Value |
|
||||
| :-------------------- | :------------------------------------------------------- |
|
||||
| `id` | "X-GitHub-Delivery" HTTP header value |
|
||||
| `source` | "repository.url" value |
|
||||
| `specversion` | `1.0` |
|
||||
| `type` | `com.github.projects_v2_status_update.` + "action" value |
|
||||
| `datacontentencoding` | Omit |
|
||||
| `datacontenttype` | `application/json` |
|
||||
| `dataschema` | Omit |
|
||||
| `subject` | "projects_v2_status_update.id" value |
|
||||
| `time` | "projects_v2_status_update.updated_at" value |
|
||||
| `data` | Content of HTTP request body |
|
||||
|
||||
### PublicEvent
|
||||
|
||||
| CloudEvents Attribute | Value |
|
||||
|
@ -490,6 +732,21 @@ based on the specified event.
|
|||
| `time` | "pull_request.updated_at" value |
|
||||
| `data` | Content of HTTP request body |
|
||||
|
||||
### PullRequestReviewThreadEvent
|
||||
|
||||
| CloudEvents Attribute | Value |
|
||||
| :-------------------- | :-------------------------------------------------------- |
|
||||
| `id` | "X-GitHub-Delivery" HTTP header value |
|
||||
| `source` | "pull_request.url" value |
|
||||
| `specversion` | `1.0` |
|
||||
| `type` | `com.github.pull_request_review_thread.` + "action" value |
|
||||
| `datacontentencoding` | Omit |
|
||||
| `datacontenttype` | `application/json` |
|
||||
| `dataschema` | Omit |
|
||||
| `subject` | "pull_request.id" value |
|
||||
| `time` | Current time |
|
||||
| `data` | Content of HTTP request body |
|
||||
|
||||
### PushEvent
|
||||
|
||||
| CloudEvents Attribute | Value |
|
||||
|
@ -550,6 +807,36 @@ based on the specified event.
|
|||
| `time` | "repository.updated_at" value |
|
||||
| `data` | Content of HTTP request body |
|
||||
|
||||
### RepositoryAdvisoryEvent
|
||||
|
||||
| CloudEvents Attribute | Value |
|
||||
| :-------------------- | :------------------------------------------------- |
|
||||
| `id` | "X-GitHub-Delivery" HTTP header value |
|
||||
| `source` | "repository.url" value |
|
||||
| `specversion` | `1.0` |
|
||||
| `type` | `com.github.repository_advisory.` + "action" value |
|
||||
| `datacontentencoding` | Omit |
|
||||
| `datacontenttype` | `application/json` |
|
||||
| `dataschema` | Omit |
|
||||
| `subject` | "repository_advisory.ghsa_id" value |
|
||||
| `time` | "repository_advisory.updated_at" value |
|
||||
| `data` | Content of HTTP request body |
|
||||
|
||||
### RepositoryDispatchEvent
|
||||
|
||||
| CloudEvents Attribute | Value |
|
||||
| :-------------------- | :------------------------------------------------ |
|
||||
| `id` | "X-GitHub-Delivery" HTTP header value |
|
||||
| `source` | "repository.owner.url" value |
|
||||
| `specversion` | `1.0` |
|
||||
| `type` | `com.github.repository_dispatch` + "action" value |
|
||||
| `datacontentencoding` | Omit |
|
||||
| `datacontenttype` | `application/json` |
|
||||
| `dataschema` | Omit |
|
||||
| `subject` | Omit |
|
||||
| `time` | Current time |
|
||||
| `data` | Content of HTTP request body |
|
||||
|
||||
### RepositoryImportEvent
|
||||
|
||||
| CloudEvents Attribute | Value |
|
||||
|
@ -565,6 +852,21 @@ based on the specified event.
|
|||
| `time` | "repository.updated_at" value |
|
||||
| `data` | Content of HTTP request body |
|
||||
|
||||
### RepositoryRulesetEvent
|
||||
|
||||
| CloudEvents Attribute | Value |
|
||||
| :-------------------- | :----------------------------------------------- |
|
||||
| `id` | "X-GitHub-Delivery" HTTP header value |
|
||||
| `source` | "repository.owner.url" value |
|
||||
| `specversion` | `1.0` |
|
||||
| `type` | `com.github.repository_ruleset` + "action" value |
|
||||
| `datacontentencoding` | Omit |
|
||||
| `datacontenttype` | `application/json` |
|
||||
| `dataschema` | Omit |
|
||||
| `subject` | "repository.name" value |
|
||||
| `time` | "repository.updated_at" value |
|
||||
| `data` | Content of HTTP request body |
|
||||
|
||||
### RepositoryVulnerabilityAlertEvent
|
||||
|
||||
| CloudEvents Attribute | Value |
|
||||
|
@ -580,6 +882,36 @@ based on the specified event.
|
|||
| `time` | Current time # repository.updated_id ? |
|
||||
| `data` | Content of HTTP request body |
|
||||
|
||||
### SecretScanningAlertEvent
|
||||
|
||||
| CloudEvents Attribute | Value |
|
||||
| :-------------------- | :---------------------------------------------------------------------- |
|
||||
| `id` | "X-GitHub-Delivery" HTTP header value |
|
||||
| `source` | "repository.url" value |
|
||||
| `specversion` | `1.0` |
|
||||
| `type` | `com.github.secret_scanning_alert.` + "action" value |
|
||||
| `datacontentencoding` | Omit |
|
||||
| `datacontenttype` | `application/json` |
|
||||
| `dataschema` | Omit |
|
||||
| `subject` | "alert.number" value |
|
||||
| `time` | "alert.updated_at" value , unless "null", then "alert.created_at" value |
|
||||
| `data` | Content of HTTP request body |
|
||||
|
||||
### SecretScanningAlertLocationEvent
|
||||
|
||||
| CloudEvents Attribute | Value |
|
||||
| :-------------------- | :---------------------------------------------------------------------- |
|
||||
| `id` | "X-GitHub-Delivery" HTTP header value |
|
||||
| `source` | "repository.url" value |
|
||||
| `specversion` | `1.0` |
|
||||
| `type` | `com.github.secret_scanning_alert_location.` + "action" value |
|
||||
| `datacontentencoding` | Omit |
|
||||
| `datacontenttype` | `application/json` |
|
||||
| `dataschema` | Omit |
|
||||
| `subject` | "alert.number" value |
|
||||
| `time` | "alert.updated_at" value , unless "null", then "alert.created_at" value |
|
||||
| `data` | Content of HTTP request body |
|
||||
|
||||
### SecurityAdvisoryEvent
|
||||
|
||||
| CloudEvents Attribute | Value |
|
||||
|
@ -595,6 +927,36 @@ based on the specified event.
|
|||
| `time` | "security_advisory.updated_at" value |
|
||||
| `data` | Content of HTTP request body |
|
||||
|
||||
### SecurityAndAnalysisEvent
|
||||
|
||||
| CloudEvents Attribute | Value |
|
||||
| :-------------------- | :------------------------------------ |
|
||||
| `id` | "X-GitHub-Delivery" HTTP header value |
|
||||
| `source` | "repository.url" value |
|
||||
| `specversion` | `1.0` |
|
||||
| `type` | `com.github.security_and_analysis` |
|
||||
| `datacontentencoding` | Omit |
|
||||
| `datacontenttype` | `application/json` |
|
||||
| `dataschema` | Omit |
|
||||
| `subject` | Omit |
|
||||
| `time` | Current time |
|
||||
| `data` | Content of HTTP request body |
|
||||
|
||||
### SponsorshipEvent
|
||||
|
||||
| CloudEvents Attribute | Value |
|
||||
| :-------------------- | :----------------------------------------- |
|
||||
| `id` | "X-GitHub-Delivery" HTTP header value |
|
||||
| `source` | "repository.url" value |
|
||||
| `specversion` | `1.0` |
|
||||
| `type` | `com.github.sponsorship.` + "action" value |
|
||||
| `datacontentencoding` | Omit |
|
||||
| `datacontenttype` | `application/json` |
|
||||
| `dataschema` | Omit |
|
||||
| `subject` | "sponsorship.sponsor.login" |
|
||||
| `time` | Current time |
|
||||
| `data` | Content of HTTP request body |
|
||||
|
||||
### StarEvent
|
||||
|
||||
| CloudEvents Attribute | Value |
|
||||
|
@ -670,3 +1032,47 @@ based on the specified event.
|
|||
| `time` | Current time |
|
||||
| `data` | Content of HTTP request body |
|
||||
|
||||
### WorkflowDispatchEvent
|
||||
|
||||
| CloudEvents Attribute | Value |
|
||||
| :-------------------- | :------------------------------------ |
|
||||
| `id` | "X-GitHub-Delivery" HTTP header value |
|
||||
| `source` | "repository.url" value |
|
||||
| `specversion` | `1.0` |
|
||||
| `type` | `com.github.workflow_dispatch` |
|
||||
| `datacontentencoding` | Omit |
|
||||
| `datacontenttype` | `application/json` |
|
||||
| `dataschema` | Omit |
|
||||
| `subject` | "workflow" value |
|
||||
| `time` | Current time |
|
||||
| `data` | Content of HTTP request body |
|
||||
|
||||
### WorkflowJobEvent
|
||||
|
||||
| CloudEvents Attribute | Value |
|
||||
| :-------------------- | :------------------------------------------ |
|
||||
| `id` | "X-GitHub-Delivery" HTTP header value |
|
||||
| `source` | "repository.url" value |
|
||||
| `specversion` | `1.0` |
|
||||
| `type` | `com.github.workflow_job.` + "action" value |
|
||||
| `datacontentencoding` | Omit |
|
||||
| `datacontenttype` | `application/json` |
|
||||
| `dataschema` | Omit |
|
||||
| `subject` | "workflow_job.name" value |
|
||||
| `time` | Current time |
|
||||
| `data` | Content of HTTP request body |
|
||||
|
||||
### WorkflowRunEvent
|
||||
|
||||
| CloudEvents Attribute | Value |
|
||||
| :-------------------- | :------------------------------------------ |
|
||||
| `id` | "X-GitHub-Delivery" HTTP header value |
|
||||
| `source` | "repository.url" value |
|
||||
| `specversion` | `1.0` |
|
||||
| `type` | `com.github.workflow_run.` + "action" value |
|
||||
| `datacontentencoding` | Omit |
|
||||
| `datacontenttype` | `application/json` |
|
||||
| `dataschema` | Omit |
|
||||
| `subject` | "workflow.name" value |
|
||||
| `time` | Current time |
|
||||
| `data` | Content of HTTP request body |
|
|
@ -1,14 +1,10 @@
|
|||
# AMQP Protocol Binding for CloudEvents - Version 1.0.1
|
||||
# AMQP Protocol Binding for CloudEvents - Version 1.0.3-wip
|
||||
|
||||
## Abstract
|
||||
|
||||
The AMQP Protocol Binding for CloudEvents defines how events are mapped to
|
||||
OASIS AMQP 1.0 ([OASIS][oasis-amqp-1.0]; ISO/IEC 19464:2014) messages.
|
||||
|
||||
## Status of this document
|
||||
|
||||
This document is a working draft.
|
||||
|
||||
## Table of Contents
|
||||
|
||||
1. [Introduction](#1-introduction)
|
||||
|
@ -50,7 +46,7 @@ AMQP 1.0 messages.
|
|||
AMQP-based messaging and eventing infrastructures often provide higher-level
|
||||
programming-level abstractions that do not expose all AMQP protocol elements, or
|
||||
map AMQP protocol elements or names to proprietary constructs. This
|
||||
specification uses AMQP terminology, and implementers can refer the the
|
||||
specification uses AMQP terminology, and implementers can refer to the
|
||||
respective infrastructure's AMQP documentation to determine the mapping into a
|
||||
programming-level abstraction.
|
||||
|
||||
|
@ -59,9 +55,10 @@ format][message-format].
|
|||
|
||||
### 1.3. Content Modes
|
||||
|
||||
The specification defines two content modes for transferring events:
|
||||
_structured_ and _binary_. Every compliant implementation SHOULD support both
|
||||
modes.
|
||||
The CloudEvents specification defines three content modes for transferring
|
||||
events: _structured_, _binary_ and _batch_. The AMQP protocol binding does not
|
||||
currently support the batch content mode. Every compliant implementation SHOULD
|
||||
support both structured and binary modes.
|
||||
|
||||
In the _structured_ content mode, event metadata attributes and event data are
|
||||
placed into the AMQP message's [application data][data] section using an
|
||||
|
@ -75,7 +72,7 @@ AMQP [application-properties][app-properties] section.
|
|||
|
||||
### 1.4. Event Formats
|
||||
|
||||
Event formats, used with the _stuctured_ content mode, define how an event is
|
||||
Event formats, used with the _structured_ content mode, define how an event is
|
||||
expressed in a particular data format. All implementations of this specification
|
||||
that support the _structured_ content mode MUST support the [JSON event
|
||||
format][json-format].
|
||||
|
@ -108,9 +105,9 @@ an application, but are not defined here.
|
|||
|
||||
The receiver of the event can distinguish between the two modes by inspecting
|
||||
the `content-type` message property field. If the value is prefixed with the
|
||||
CloudEvents media type `application/cloudevents`, indicating the use of a known
|
||||
[event format](#14-event-formats), the receiver uses _structured_ mode,
|
||||
otherwise it defaults to _binary_ mode.
|
||||
CloudEvents media type `application/cloudevents` (matched case-insensitively),
|
||||
indicating the use of a known [event format](#14-event-formats), the receiver
|
||||
uses _structured_ mode, otherwise it defaults to _binary_ mode.
|
||||
|
||||
If a receiver detects the CloudEvents media type, but with an event format that
|
||||
it cannot handle, for instance `application/cloudevents+avro`, it MAY still
|
||||
|
@ -173,14 +170,26 @@ time of the submission or revision.
|
|||
|
||||
##### 3.1.3.1 AMQP Application Property Names
|
||||
|
||||
CloudEvent attributes are prefixed with "cloudEvents:" for use in the
|
||||
[application-properties][app-properties] section.
|
||||
CloudEvent attributes MUST be prefixed with either "cloudEvents_" or
|
||||
"cloudEvents:" for use in the application-properties section.
|
||||
|
||||
The '\_' separator character SHOULD be preferred in the interest of
|
||||
compatibility with JMS 2.0 clients and JMS message selectors where the ':'
|
||||
separator is not permitted for property identifiers (see section 3.8.1.1 of
|
||||
[JMS2.0][JMS20]). Any single message MUST use the same separator for all
|
||||
CloudEvents attributes, but a single queue MAY contain messages which use
|
||||
different separators.
|
||||
|
||||
CloudEvents AMQP consumers SHOULD understand the "cloudEvents" prefix with both
|
||||
the '\_' and the ':' separators as permitted within the constraints of the
|
||||
client model. JMS 2.0 AMQP consumers MUST understand the '\_' separator; they
|
||||
cannot understand the ':' separator as per the cited JMS constraints.
|
||||
|
||||
Examples:
|
||||
|
||||
* `time` maps to `cloudEvents:time`
|
||||
* `id` maps to `cloudEvents:id`
|
||||
* `specversion` maps to `cloudEvents:specversion`
|
||||
* `time` maps to `cloudEvents_time`
|
||||
* `id` maps to `cloudEvents_id`
|
||||
* `specversion` maps to `cloudEvents_specversion`
|
||||
|
||||
##### 3.1.3.2 AMQP Application Property Values
|
||||
|
||||
|
@ -312,9 +321,10 @@ content-type: application/cloudevents+json; charset=utf-8
|
|||
Format
|
||||
- [OASIS-AMQP-1.0][oasis-amqp-1.0] OASIS Advanced Message Queuing Protocol
|
||||
(AMQP) Version 1.0
|
||||
- [JMS20][JMS20] JSR-343 Java Message Service 2.0
|
||||
|
||||
[ce]: ./spec.md
|
||||
[json-format]: ./json-format.md
|
||||
[ce]: ../spec.md
|
||||
[json-format]: ../formats/json-format.md
|
||||
[content-type]: https://tools.ietf.org/html/rfc7231#section-3.1.1.5
|
||||
[json-value]: https://tools.ietf.org/html/rfc7159#section-3
|
||||
[rfc2046]: https://tools.ietf.org/html/rfc2046
|
||||
|
@ -327,3 +337,9 @@ content-type: application/cloudevents+json; charset=utf-8
|
|||
[message-format]: http://docs.oasis-open.org/amqp/core/v1.0/os/amqp-core-messaging-v1.0-os.html#section-message-format
|
||||
[data]: http://docs.oasis-open.org/amqp/core/v1.0/os/amqp-core-messaging-v1.0-os.html#type-data
|
||||
[app-properties]: http://docs.oasis-open.org/amqp/core/v1.0/os/amqp-core-messaging-v1.0-os.html#type-application-properties
|
||||
[amqp-boolean]: http://docs.oasis-open.org/amqp/core/v1.0/os/amqp-core-types-v1.0-os.html#type-boolean
|
||||
[amqp-long]: http://docs.oasis-open.org/amqp/core/v1.0/os/amqp-core-types-v1.0-os.html#type-long
|
||||
[amqp-binary]: http://docs.oasis-open.org/amqp/core/v1.0/os/amqp-core-types-v1.0-os.html#type-binary
|
||||
[amqp-string]: http://docs.oasis-open.org/amqp/core/v1.0/os/amqp-core-types-v1.0-os.html#type-string
|
||||
[amqp-timestamp]: http://docs.oasis-open.org/amqp/core/v1.0/os/amqp-core-types-v1.0-os.html#type-timestamp
|
||||
[jms20]: https://jcp.org/aboutJava/communityprocess/final/jsr343/index.html
|
|
@ -1,14 +1,10 @@
|
|||
# HTTP Protocol Binding for CloudEvents - Version 1.0.1
|
||||
# HTTP Protocol Binding for CloudEvents - Version 1.0.3-wip
|
||||
|
||||
## Abstract
|
||||
|
||||
The HTTP Protocol Binding for CloudEvents defines how events are mapped to HTTP
|
||||
1.1 request and response messages.
|
||||
|
||||
## Status of this document
|
||||
|
||||
This document is a working draft.
|
||||
|
||||
## Table of Contents
|
||||
|
||||
1. [Introduction](#1-introduction)
|
||||
|
@ -65,9 +61,10 @@ which is compatible with HTTP 1.1 semantics.
|
|||
|
||||
### 1.3. Content Modes
|
||||
|
||||
This specification defines three content modes for transferring events:
|
||||
_binary_, _structured_ and _batched_. Every compliant implementation SHOULD
|
||||
support the _structured_ and _binary_ modes.
|
||||
The CloudEvents specification defines three content modes for transferring
|
||||
events: _structured_, _binary_ and _batch_. The HTTP protocol binding supports
|
||||
all three content modes. Every compliant implementation SHOULD
|
||||
support both structured and binary modes.
|
||||
|
||||
In the _binary_ content mode, the value of the event `data` is placed into the
|
||||
HTTP request, or response, body as-is, with the `datacontenttype` attribute
|
||||
|
@ -99,7 +96,7 @@ can be used with the _batched_ content mode.
|
|||
|
||||
This specification does not introduce any new security features for HTTP, or
|
||||
mandate specific existing features to be used. This specification applies
|
||||
identically to [HTTP over TLS]([RFC2818][RFC2818]).
|
||||
identically to [HTTP over TLS][rfc2818].
|
||||
|
||||
## 2. Use of CloudEvents Attributes
|
||||
|
||||
|
@ -141,10 +138,10 @@ gesture SHOULD allow the receiver to choose the maximum size of a batch.
|
|||
|
||||
The receiver of the event can distinguish between the three modes by inspecting
|
||||
the `Content-Type` header value. If the value is prefixed with the CloudEvents
|
||||
media type `application/cloudevents`, indicating the use of a known
|
||||
[event format](#14-event-formats), the receiver uses _structured_ mode. If the
|
||||
value is prefixed with `application/cloudevents-batch`, the receiver uses the
|
||||
_batched_ mode. Otherwise it defaults to _binary_ mode.
|
||||
media type `application/cloudevents` (matched case-insensitively), indicating
|
||||
the use of a known [event format](#14-event-formats), the receiver uses
|
||||
_structured_ mode. If the value is prefixed with `application/cloudevents-batch`,
|
||||
the receiver uses the _batched_ mode. Otherwise it defaults to _binary_ mode.
|
||||
|
||||
If a receiver detects the CloudEvents media type, but with an event format that
|
||||
it cannot handle, for instance `application/cloudevents+avro`, it MAY still
|
||||
|
@ -213,16 +210,75 @@ and per [RFC7230, section 3][rfc7230-section-3], HTTP headers MUST only use
|
|||
printable characters from the US-ASCII character set, and are terminated by a
|
||||
CRLF sequence with OPTIONAL whitespace around the header value.
|
||||
|
||||
String values MUST be percent-encoded as described in [RFC3986, section
|
||||
2.4][rfc3986-section-2-4] before applying the header encoding rules described in
|
||||
[RFC7230, section 3.2.6][rfc7230-section-3-2-6].
|
||||
When encoding a CloudEvent as an HTTP message, string values
|
||||
represented as HTTP header values MUST be percent-encoded as
|
||||
described below. This is compatible with [RFC3986, section
|
||||
2.1][rfc3986-section-2-1] but is more specific about what needs
|
||||
encoding. The resulting string SHOULD NOT be further encoded.
|
||||
(Rationale: quoted string escaping is unnecessary when every space
|
||||
and double-quote character is already percent-encoded.)
|
||||
|
||||
When decoding an HTTP message into a CloudEvent, these rules MUST be applied in
|
||||
reverse -- [RFC7230, section 3.2.6][rfc7230-section-3-2-6] decoding to an ASCII
|
||||
string, and then a **single round** of percent-decoding as described in
|
||||
[RFC3986, section 2.4][rfc3986-section-2-4] to produce a valid UTF-8 String.
|
||||
(Note that applying percent-decoding an incorrect number of times can result in
|
||||
message corruption or security issues.)
|
||||
When decoding an HTTP message into a CloudEvent, any HTTP header
|
||||
value MUST first be unescaped with respect to double-quoted strings,
|
||||
as described in [RFC7230, section 3.2.6][rfc7230-section-3-2-6]. A single
|
||||
round of percent-decoding MUST then be performed as described
|
||||
below. HTTP headers for CloudEvent attribute values do not support
|
||||
parenthetical comments, so the initial unescaping only needs to handle
|
||||
double-quoted values, including processing backslash escapes within
|
||||
double-quoted values. Header values produced via the
|
||||
percent-encoding described here will never include double-quoted
|
||||
values, but they MUST be supported when receiving events, for
|
||||
compatibility with older versions of this specification which did
|
||||
not require double-quote and space characters to be percent-encoded.
|
||||
|
||||
Percent encoding is performed by considering each Unicode character
|
||||
within the attribute's canonical string representation. Any
|
||||
character represented in memory as a [Unicode surrogate
|
||||
pair][surrogate-pair] MUST be treated as a single Unicode character.
|
||||
The following characters MUST be percent-encoded:
|
||||
|
||||
- Space (U+0020)
|
||||
- Double-quote (U+0022)
|
||||
- Percent (U+0025)
|
||||
- Any characters outside the printable ASCII range of U+0021-U+007E
|
||||
inclusive
|
||||
|
||||
Attribute values are already constrained to prohibit characters in
|
||||
the range U+0000-U+001F inclusive and U+007F-U+009F inclusive;
|
||||
however for simplicity and to account for potential future changes,
|
||||
it is RECOMMENDED that any HTTP header encoding implementation treats
|
||||
such characters as requiring percent-encoding.
|
||||
|
||||
Space and double-quote are encoded to avoid requiring any further
|
||||
quoting. Percent is encoded to avoid ambiguity with percent-encoding
|
||||
itself.
|
||||
|
||||
Steps to encode a Unicode character:
|
||||
|
||||
- Encode the character using UTF-8, to obtain a byte sequence.
|
||||
- Encode each byte within the sequence as `%xy` where `x` is a
|
||||
hexadecimal representation of the most significant 4 bits of the byte,
|
||||
and `y` is a hexadecimal representation of the least significant 4
|
||||
bits of the byte.
|
||||
|
||||
Percent-encoding SHOULD be performed using upper-case for values A-F,
|
||||
but decoding MUST accept lower-case values.
|
||||
|
||||
When performing percent-decoding (when decoding an HTTP message to a
|
||||
CloudEvent), values that have been unnecessarily percent-encoded MUST be
|
||||
accepted, but encoded byte sequences which are invalid in UTF-8 MUST be
|
||||
rejected. (For example, "%C0%A0" is an overlong encoding of U+0020, and
|
||||
MUST be rejected.)
|
||||
|
||||
Example: a header value of "Euro € 😀" SHOULD be encoded as follows:
|
||||
|
||||
- The characters, 'E', 'u', 'r', 'o' do not require encoding
|
||||
- Space, the Euro symbol, and the grinning face emoji require encoding.
|
||||
They are characters U+0020, U+20AC and U+1F600 respectively.
|
||||
- The encoded HTTP header value is therefore "Euro%20%E2%82%AC%20%F0%9F%98%80"
|
||||
where "%20" is the encoded form of space, "%E2%82%AC" is the encoded form
|
||||
of the Euro symbol, and "%F0%9F%98%80" is the encoded form of the
|
||||
grinning face emoji.
|
||||
|
||||
#### 3.1.4. Examples
|
||||
|
||||
|
@ -346,14 +402,12 @@ Content-Length: nnnn
|
|||
|
||||
In the _batched_ content mode several events are batched into a single HTTP
|
||||
request or response body. The chosen [event format](#14-event-formats) MUST
|
||||
define how a batch is represented. Based on the [JSON format][json-format] (that
|
||||
MUST be supported by any compliant implementation), the [JSON Batch
|
||||
format][json-batch-format] is an event format that supports batching.
|
||||
define how a batch is represented, including a suitable media type.
|
||||
|
||||
#### 3.3.1. HTTP Content-Type
|
||||
|
||||
The [HTTP `Content-Type`][content-type] header MUST be set to the media type of
|
||||
an [event format](#14-event-formats).
|
||||
the batch mode for the [event format](#14-event-formats).
|
||||
|
||||
Example for the [JSON Batch format][json-batch-format]:
|
||||
|
||||
|
@ -369,10 +423,6 @@ all event attributes, and `data`, are represented.
|
|||
The batch of events is then rendered in accordance with the event format
|
||||
specification and the resulting data becomes the HTTP message body.
|
||||
|
||||
The batch MAY be empty. All batched CloudEvents MUST have the same `specversion`
|
||||
attribute. Other attributes MAY differ, including the `datacontenttype`
|
||||
attribute.
|
||||
|
||||
#### 3.3.3. Examples
|
||||
|
||||
This example shows two batched CloudEvents, sent with a PUT request:
|
||||
|
@ -462,11 +512,11 @@ Content-Length: nnnn
|
|||
Content
|
||||
- [RFC7540][rfc7540] Hypertext Transfer Protocol Version 2 (HTTP/2)
|
||||
|
||||
[ce]: ./spec.md
|
||||
[ce-message]: ./spec.md#message
|
||||
[ce-types]: ./spec.md#type-system
|
||||
[json-format]: ./json-format.md
|
||||
[json-batch-format]: ./json-format.md#4-json-batch-format
|
||||
[ce]: ../spec.md
|
||||
[ce-message]: ../spec.md#message
|
||||
[ce-types]: ../spec.md#type-system
|
||||
[json-format]: ../formats/json-format.md
|
||||
[json-batch-format]: ../formats/json-format.md#4-json-batch-format
|
||||
[content-type]: https://tools.ietf.org/html/rfc7231#section-3.1.1.5
|
||||
[json-value]: https://tools.ietf.org/html/rfc7159#section-3
|
||||
[json-array]: https://tools.ietf.org/html/rfc7159#section-5
|
||||
|
@ -475,7 +525,7 @@ Content-Length: nnnn
|
|||
[rfc2818]: https://tools.ietf.org/html/rfc2818
|
||||
[rfc3629]: https://tools.ietf.org/html/rfc3629
|
||||
[rfc3986]: https://tools.ietf.org/html/rfc3986
|
||||
[rfc3986-section-2-4]: https://tools.ietf.org/html/rfc3986#section-2.4
|
||||
[rfc3986-section-2-1]: https://tools.ietf.org/html/rfc3986#section-2.1
|
||||
[rfc4627]: https://tools.ietf.org/html/rfc4627
|
||||
[rfc4648]: https://tools.ietf.org/html/rfc4648
|
||||
[rfc6839]: https://tools.ietf.org/html/rfc6839#section-3.1
|
||||
|
@ -487,3 +537,4 @@ Content-Length: nnnn
|
|||
[rfc7231]: https://tools.ietf.org/html/rfc7231
|
||||
[rfc7231-section-4]: https://tools.ietf.org/html/rfc7231#section-4
|
||||
[rfc7540]: https://tools.ietf.org/html/rfc7540
|
||||
[surrogate-pair]: http://unicode.org/glossary/#surrogate_pair
|
|
@ -1,14 +1,10 @@
|
|||
# Kafka Protocol Binding for CloudEvents - Version 1.0.1
|
||||
# Kafka Protocol Binding for CloudEvents - Version 1.0.3-wip
|
||||
|
||||
## Abstract
|
||||
|
||||
The [Kafka][kafka] Protocol Binding for CloudEvents defines how events are
|
||||
mapped to [Kafka messages][kafka-message-format].
|
||||
|
||||
## Status of this document
|
||||
|
||||
This document is a working draft.
|
||||
|
||||
## Table of Contents
|
||||
|
||||
1. [Introduction](#1-introduction)
|
||||
|
@ -34,9 +30,9 @@ This document is a working draft.
|
|||
## 1. Introduction
|
||||
|
||||
[CloudEvents][ce] is a standardized and protocol-agnostic definition of the
|
||||
structure and metadata description of events. This specification defines how
|
||||
the elements defined in the CloudEvents specification are to be used in the
|
||||
Kafka protocol as [Kafka messages][kafka-message-format] (aka Kafka records).
|
||||
structure and metadata description of events. This specification defines how the
|
||||
elements defined in the CloudEvents specification are to be used in the Kafka
|
||||
protocol as [Kafka messages][kafka-message-format] (aka Kafka records).
|
||||
|
||||
### 1.1. Conformance
|
||||
|
||||
|
@ -47,8 +43,8 @@ interpreted as described in [RFC2119][rfc2119].
|
|||
### 1.2. Relation to Kafka
|
||||
|
||||
This specification does not prescribe rules constraining transfer or settlement
|
||||
of event messages with Kafka; it solely defines how CloudEvents are expressed
|
||||
in the Kafka protocol as [Kafka messages][kafka-message-format].
|
||||
of event messages with Kafka; it solely defines how CloudEvents are expressed in
|
||||
the Kafka protocol as [Kafka messages][kafka-message-format].
|
||||
|
||||
The Kafka documentation uses "message" and "record" somewhat interchangeably and
|
||||
therefore the terms are to be considered synonyms in this specification as well.
|
||||
|
@ -59,12 +55,29 @@ record is typically chosen based on the key's value. Kafka clients accomplish
|
|||
this by using a hash function.
|
||||
|
||||
This binding specification defines how attributes and data of a CloudEvent is
|
||||
mapped to the value, key, and headers sections of a Kafka message.
|
||||
mapped to the value and headers sections of a Kafka record.
|
||||
|
||||
Generally, the user SHOULD configure the key and/or the partition of the Kafka
|
||||
record in a way that makes more sense for his/her use case (e.g. streaming
|
||||
applications), in order to co-partition values, define relationships between
|
||||
events, etc. This spec provides an OPTIONAL definition to map the key section of
|
||||
the Kafka record, without constraining the user to implement it nor use it. An
|
||||
example use case of this definition is when the sink of the event is a Kafka
|
||||
topic, but the source is another transport (e.g. HTTP), and the user needs a way
|
||||
to key the record. As a counter example, it doesn't make sense to use it when
|
||||
the sink and source are Kafka topics, because this might cause the re-keying of
|
||||
the records.
|
||||
|
||||
### 1.3. Content Modes
|
||||
|
||||
The specification defines two content modes for transferring events:
|
||||
_structured_ and _binary_.
|
||||
The CloudEvents specification defines three content modes for transferring
|
||||
events: _structured_, _binary_ and _batch_. The Kafka protocol binding does not
|
||||
currently support the batch content mode. Every compliant implementation SHOULD
|
||||
support both structured and binary modes.
|
||||
|
||||
The specification defines three content modes for transferring events:
|
||||
_structured_, _binary_ and _batch_. The Kafka protocol binding does not
|
||||
currently support the _batch_ content mode.
|
||||
|
||||
In the _structured_ content mode, event metadata attributes and event data are
|
||||
placed into the Kafka message value section using an
|
||||
|
@ -72,13 +85,13 @@ placed into the Kafka message value section using an
|
|||
|
||||
In the _binary_ content mode, the value of the event `data` MUST be placed into
|
||||
the Kafka message's value section as-is, with the `content-type` header value
|
||||
declaring its media type; all other event attributes MUST be mapped to the
|
||||
Kafka message's [header section][kafka-message-header].
|
||||
declaring its media type; all other event attributes MUST be mapped to the Kafka
|
||||
message's [header section][kafka-message-header].
|
||||
|
||||
Implementations that use Kafka 0.11.0.0 and above MAY use either _binary_ or
|
||||
_structured_ modes. Implementations that use Kafka 0.10.x.x and below MUST only
|
||||
use _structured_ mode and encode the event in JSON. This is because older
|
||||
versions of Kafka lacked support for message level headers.
|
||||
use _structured_ mode. This is because older versions of Kafka lacked
|
||||
support for message level headers.
|
||||
|
||||
### 1.4. Event Formats
|
||||
|
||||
|
@ -99,16 +112,16 @@ attributes.
|
|||
|
||||
### 2.1. data
|
||||
|
||||
`data` is assumed to contain opaque application data that is
|
||||
encoded as declared by the `datacontenttype` attribute.
|
||||
`data` is assumed to contain opaque application data that is encoded as declared
|
||||
by the `datacontenttype` attribute.
|
||||
|
||||
An application is free to hold the information in any in-memory representation
|
||||
of its choosing, but as the value is transposed into Kafka as defined in this
|
||||
specification, core Kafka provides data available as a sequence of bytes.
|
||||
|
||||
For instance, if the declared `datacontenttype` is
|
||||
`application/json;charset=utf-8`, the expectation is that the `data`
|
||||
value is made available as [UTF-8][rfc3629] encoded JSON text.
|
||||
`application/json;charset=utf-8`, the expectation is that the `data` value is
|
||||
made available as [UTF-8][rfc3629] encoded JSON text.
|
||||
|
||||
## 3. Kafka Message Mapping
|
||||
|
||||
|
@ -118,16 +131,15 @@ particular content mode might be defined by an application, but are not defined
|
|||
here.
|
||||
|
||||
The receiver of the event can distinguish between the two content modes by
|
||||
inspecting the `content-type` [Header][kafka-message-header] of the
|
||||
Kafka message. If the header is present and its value is prefixed with the
|
||||
CloudEvents media type `application/cloudevents`, indicating the use of a known
|
||||
[event format](#14-event-formats), the receiver uses _structured_ mode,
|
||||
otherwise it defaults to _binary_ mode.
|
||||
inspecting the `content-type` [Header][kafka-message-header] of the Kafka
|
||||
message. If the header is present and its value is prefixed with the CloudEvents
|
||||
media type `application/cloudevents` (matched case-insensitively),
|
||||
indicating the use of a known [event format](#14-event-formats), the receiver
|
||||
uses _structured_ mode, otherwise it defaults to _binary_ mode.
|
||||
|
||||
If a receiver finds a CloudEvents media type as per the above rule, but with an
|
||||
event format that it cannot handle, for instance
|
||||
`application/cloudevents+avro`, it MAY still treat the event as binary and
|
||||
forward it to another party as-is.
|
||||
event format that it cannot handle, for instance `application/cloudevents+avro`,
|
||||
it MAY still treat the event as binary and forward it to another party as-is.
|
||||
|
||||
When the `content-type` header value is not prefixed with the CloudEvents media
|
||||
type, knowing when the message ought to be parsed as a CloudEvent can be a
|
||||
|
@ -138,22 +150,22 @@ CloudEvents attributes as headers then it's probably a CloudEvent. However, as
|
|||
with all CloudEvent messages, if it does not adhere to all of the normative
|
||||
language of this specification then it is not a valid CloudEvent.
|
||||
|
||||
If the `content-type` header is not present then the receiver uses
|
||||
_structured_ mode with the JSON event format.
|
||||
|
||||
### 3.1. Key Mapping
|
||||
|
||||
The 'key' of the Kafka message is populated by a "Key Mapper" function, which
|
||||
might map the key directly from one of the CloudEvent's attributes, but might
|
||||
also use information from the application environment, from the CloudEvent's
|
||||
data or other sources.
|
||||
Every implementation MUST, by default, map the user provided record key to the
|
||||
Kafka record key.
|
||||
|
||||
The 'key' of the Kafka message MAY be populated by a "Key Mapper" function,
|
||||
which might map the key directly from one of the CloudEvent's attributes, but
|
||||
might also use information from the application environment, from the
|
||||
CloudEvent's data or other sources.
|
||||
|
||||
The shape and configuration of the "Key Mapper" function is implementation
|
||||
specific.
|
||||
|
||||
Every implementation SHOULD provide a default "Key Mapper" implementation that
|
||||
maps the [Partitioning](extensions/partitioning.md) `partitionkey` attribute
|
||||
value to the 'key' of the Kafka message as-is, if present.
|
||||
Every implementation SHOULD provide an opt-in "Key Mapper" implementation that
|
||||
maps the [Partitioning](../extensions/partitioning.md) `partitionkey` attribute
|
||||
value to the 'key' of the Kafka message as-is, if present.
|
||||
|
||||
A mapping function MUST NOT modify the CloudEvent. This means that the
|
||||
aforementioned `partitionkey` attribute MUST still be included with the
|
||||
|
@ -176,10 +188,16 @@ directly to the CloudEvents `datacontenttype` attribute.
|
|||
The [`data`](#21-data) byte-sequence MUST be used as the value of the Kafka
|
||||
message.
|
||||
|
||||
In binary mode, the Kafka representation of a CloudEvent with no `data` is a
|
||||
Kafka message with no value. In a topic with log compaction enabled, any such
|
||||
message will represent a _tombstone_ record, as described in the
|
||||
[Kafka compaction documentation][kafka-log-compaction].
|
||||
|
||||
#### 3.2.3. Metadata Headers
|
||||
|
||||
All [CloudEvents][ce] attributes and
|
||||
[CloudEvent Attributes Extensions](primer.md#cloudevent-attribute-extensions)
|
||||
[CloudEvent Attributes
|
||||
Extensions](../primer.md#cloudevents-extension-attributes)
|
||||
with exception of `data` MUST be individually mapped to and from the Header
|
||||
fields in the Kafka message. Both header keys and header values MUST be encoded
|
||||
as UTF-8 strings.
|
||||
|
@ -197,18 +215,18 @@ Examples:
|
|||
|
||||
##### 3.2.4.2 Property Values
|
||||
|
||||
The value for each Kafka header is constructed from the respective
|
||||
header's Kafka representation, compliant with the [Kafka message
|
||||
The value for each Kafka header is constructed from the respective header's
|
||||
Kafka representation, compliant with the [Kafka message
|
||||
format][kafka-message-format] specification.
|
||||
|
||||
#### 3.2.5 Example
|
||||
|
||||
This example shows the _binary_ mode mapping of an event into the
|
||||
Kafka message. All other CloudEvents attributes
|
||||
are mapped to Kafka Header fields with prefix `ce_`.
|
||||
This example shows the _binary_ mode mapping of an event into the Kafka message.
|
||||
All other CloudEvents attributes are mapped to Kafka Header fields with prefix
|
||||
`ce_`.
|
||||
|
||||
Mind that `ce_` here does refer to the event `data`
|
||||
content carried in the payload.
|
||||
Mind that `ce_` here does refer to the event `data` content carried in the
|
||||
payload.
|
||||
|
||||
```text
|
||||
------------------ Message -------------------
|
||||
|
@ -255,12 +273,17 @@ content-type: application/cloudevents+json; charset=UTF-8
|
|||
|
||||
#### 3.3.2. Event Data Encoding
|
||||
|
||||
The chosen [event format](#14-event-formats) defines how all attributes,
|
||||
and `data`, are represented.
|
||||
The chosen [event format](#14-event-formats) defines how all attributes, and
|
||||
`data`, are represented.
|
||||
|
||||
The event metadata and data are then rendered in accordance with the [event
|
||||
format](#14-event-formats) specification and the resulting data becomes the
|
||||
Kafka application [data](#21-data) section.
|
||||
The event metadata and data are then rendered in accordance with the
|
||||
[event format](#14-event-formats) specification and the resulting data becomes
|
||||
the Kafka application [data](#21-data) section.
|
||||
|
||||
In structured mode, the Kafka representation of a CloudEvent with no `data`
|
||||
is a Kafka message which still has a data section (containing the attributes
|
||||
of the CloudEvent). Such a message does _not_ represent a tombstone record in
|
||||
a topic with log compaction enabled, unlike the representation in binary mode.
|
||||
|
||||
#### 3.3.3. Metadata Headers
|
||||
|
||||
|
@ -315,11 +338,12 @@ content-type: application/cloudevents+json; charset=UTF-8
|
|||
- [RFC7159][rfc7159] The JavaScript Object Notation (JSON) Data Interchange
|
||||
Format
|
||||
|
||||
[ce]: ./spec.md
|
||||
[json-format]: ./json-format.md
|
||||
[ce]: ../spec.md
|
||||
[json-format]: ../formats/json-format.md
|
||||
[kafka]: https://kafka.apache.org
|
||||
[kafka-message-format]: https://kafka.apache.org/documentation/#messageformat
|
||||
[kafka-message-header]: https://kafka.apache.org/documentation/#recordheader
|
||||
[kafka-log-compaction]: https://kafka.apache.org/documentation/#design_compactionbasics
|
||||
[json-value]: https://tools.ietf.org/html/rfc7159#section-3
|
||||
[rfc2046]: https://tools.ietf.org/html/rfc2046
|
||||
[rfc2119]: https://tools.ietf.org/html/rfc2119
|
|
@ -1,4 +1,4 @@
|
|||
# MQTT Protocol Binding for CloudEvents - Version 1.0.1
|
||||
# MQTT Protocol Binding for CloudEvents - Version 1.0.3-wip
|
||||
|
||||
## Abstract
|
||||
|
||||
|
@ -6,10 +6,6 @@ The MQTT Protocol Binding for CloudEvents defines how events are mapped to MQTT
|
|||
3.1.1 ([OASIS][oasis-mqtt-3.1.1]; ISO/IEC 20922:2016) and MQTT 5.0
|
||||
([OASIS][oasis-mqtt-5]) messages.
|
||||
|
||||
## Status of this document
|
||||
|
||||
This document is a working draft.
|
||||
|
||||
## Table of Contents
|
||||
|
||||
1. [Introduction](#1-introduction)
|
||||
|
@ -53,8 +49,10 @@ MQTT PUBLISH messages ([3.1.1][3-publish], [5.0][5-publish]).
|
|||
|
||||
### 1.3. Content Modes
|
||||
|
||||
The specification defines two content modes for transferring events:
|
||||
_structured_ and _binary_.
|
||||
The CloudEvents specification defines three content modes for transferring
|
||||
events: _structured_, _binary_ and _batch_. The MQTT protocol binding does not
|
||||
currently support the batch content mode. Every compliant implementation SHOULD
|
||||
support both structured and binary modes.
|
||||
|
||||
The _binary_ mode _only_ applies to MQTT 5.0, because of MQTT 3.1.1's lack of
|
||||
support for custom metadata.
|
||||
|
@ -319,12 +317,14 @@ Topic Name: mytopic
|
|||
- [RFC7159][rfc7159] The JavaScript Object Notation (JSON) Data Interchange
|
||||
Format
|
||||
|
||||
[ce]: ./spec.md
|
||||
[ce-types]: ./spec.md#type-system
|
||||
[json-format]: ./json-format.md
|
||||
[ce]: ../spec.md
|
||||
[ce-types]: ../spec.md#type-system
|
||||
[json-format]: ../formats/json-format.md
|
||||
[oasis-mqtt-3.1.1]: http://docs.oasis-open.org/mqtt/mqtt/v3.1.1/mqtt-v3.1.1.html
|
||||
[oasis-mqtt-5]: http://docs.oasis-open.org/mqtt/mqtt/v5.0/mqtt-v5.0.html
|
||||
[3-publish]: http://docs.oasis-open.org/mqtt/mqtt/v3.1.1/errata01/os/mqtt-v3.1.1-errata01-os-complete.html#_Toc442180850
|
||||
[5-content-type]: http://docs.oasis-open.org/mqtt/mqtt/v5.0/mqtt-v5.0.html#_Toc502667341
|
||||
[5-publish]: https://docs.oasis-open.org/mqtt/mqtt/v5.0/os/mqtt-v5.0-os.html#_Toc3901100
|
||||
[json-value]: https://tools.ietf.org/html/rfc7159#section-3
|
||||
[rfc2046]: https://tools.ietf.org/html/rfc2046
|
||||
[rfc2119]: https://tools.ietf.org/html/rfc2119
|
|
@ -0,0 +1,330 @@
|
|||
# NATS Protocol Binding for CloudEvents - Version 1.0.3-wip
|
||||
|
||||
## Abstract
|
||||
|
||||
The [NATS][nats] Protocol Binding for CloudEvents defines how events are mapped
|
||||
to [NATS messages][nats-msg-proto].
|
||||
|
||||
## Table of Contents
|
||||
|
||||
1. [Introduction](#1-introduction)
|
||||
|
||||
- 1.1 [Conformance](#11-conformance)
|
||||
- 1.2 [Relation to NATS](#12-relation-to-nats)
|
||||
- 1.3 [Content Modes](#13-content-modes)
|
||||
- 1.4 [Event Formats](#14-event-formats)
|
||||
- 1.5 [Security](#15-security)
|
||||
|
||||
2. [Use of CloudEvents Attributes](#2-use-of-cloudevents-attributes)
|
||||
|
||||
- 2.1 [datacontenttype Attribute](#21-datacontenttype-attribute)
|
||||
- 2.2 [data](#22-data)
|
||||
|
||||
3. [NATS Message Mapping](#3-nats-message-mapping)
|
||||
|
||||
- 3.1 [Binary Content Mode](#31-binary-content-mode)
|
||||
- 3.2 [Structured Content Mode](#32-structured-content-mode)
|
||||
|
||||
4. [References](#4-references)
|
||||
|
||||
## 1. Introduction
|
||||
|
||||
[CloudEvents][ce] is a standardized and protocol-agnostic definition of the
|
||||
structure and metadata description of events. This specification defines how the
|
||||
elements defined in the CloudEvents specification are to be used in the NATS
|
||||
protocol as client [produced][nats-pub-proto] and [consumed][nats-msg-proto]
|
||||
messages.
|
||||
|
||||
### 1.1 Conformance
|
||||
|
||||
The key words "MUST", "MUST NOT", "REQUIRED", "SHALL", "SHALL NOT", "SHOULD",
|
||||
"SHOULD NOT", "RECOMMENDED", "MAY", and "OPTIONAL" in this document are to be
|
||||
interpreted as described in [RFC2119][rfc2119].
|
||||
|
||||
### 1.2 Relation to NATS
|
||||
|
||||
This specification does not prescribe rules constraining transfer or settlement
|
||||
of event messages with NATS; it solely defines how CloudEvents are expressed in
|
||||
the NATS protocol as client messages that are [produced][nats-pub-proto] and
|
||||
[consumed][nats-msg-proto].
|
||||
|
||||
### 1.3 Content Modes
|
||||
|
||||
The CloudEvents specification defines three content modes for transferring
|
||||
events: _structured_, _binary_ and _batch_. The NATS protocol binding does not
|
||||
currently support the batch content mode. Every compliant implementation SHOULD
|
||||
support both structured and binary modes.
|
||||
|
||||
In the _binary_ content mode, event metadata attributes are placed in message
|
||||
headers and the event data are placed in the NATS message payload. Binary mode
|
||||
is supported as of [NATS 2.2][nats22], which introduced message headers.
|
||||
|
||||
In the _structured_ content mode, event metadata attributes and event data
|
||||
are placed into the NATS message payload using an [event format](#14-event-formats).
|
||||
|
||||
### 1.4 Event Formats
|
||||
|
||||
Event formats, used with the _structured_ content mode, define how an event is
|
||||
expressed in a particular data format. All implementations of this specification
|
||||
MUST support the [JSON event format][json-format].
|
||||
|
||||
### 1.5 Security
|
||||
|
||||
This specification does not introduce any new security features for NATS, or
|
||||
mandate specific existing features to be used.
|
||||
|
||||
## 2. Use of CloudEvents Attributes
|
||||
|
||||
This specification does not further define any of the [CloudEvents][ce] event
|
||||
attributes.
|
||||
|
||||
### 2.1 datacontenttype Attribute
|
||||
|
||||
The `datacontenttype` attribute is assumed to contain a media-type expression
|
||||
compliant with [RFC2046][rfc2046].
|
||||
|
||||
### 2.2 data
|
||||
|
||||
`data` is assumed to contain opaque application data that is
|
||||
encoded as declared by the `datacontenttype` attribute.
|
||||
|
||||
An application is free to hold the information in any in-memory representation
|
||||
of its choosing, but as the value is transposed into NATS as defined in this
|
||||
specification, core NATS provides data available as a sequence of bytes.
|
||||
|
||||
For instance, if the declared `datacontenttype` is
|
||||
`application/json;charset=utf-8`, the expectation is that the `data`
|
||||
value is made available as [UTF-8][rfc3629] encoded JSON text.
|
||||
|
||||
## 3. NATS Message Mapping
|
||||
|
||||
The content mode is chosen by the sender of the event, which is either the
|
||||
requesting or the responding party. Gestures that might allow solicitation
|
||||
of events using a particular mode might be defined by an application, but
|
||||
are not defined here.
|
||||
|
||||
The receiver of the event can distinguish between the two modes using two
|
||||
conditions:
|
||||
|
||||
- If the server is a version earlier than NATS 2.2, the content mode is
|
||||
always _structured_.
|
||||
- If the server is version 2.2 or above and the `Content-Type` header of
|
||||
`application/cloudevents` is present (matched case-insensitively),
|
||||
then the message is in _structured_ mode, otherwise it is using binary mode.
|
||||
|
||||
If the content mode is _structured_ then the NATS message payload MUST be
|
||||
the [JSON event format][json-format] serialized as specified by the
|
||||
[UTF-8][rfc3629] encoded JSON text for use in NATS.
|
||||
|
||||
### 3.1 Binary Content Mode
|
||||
|
||||
The _binary_ content mode accommodates any shape of event data, and allows for
|
||||
efficient transfer and without transcoding effort.
|
||||
|
||||
#### 3.1.1 Event Data Encoding
|
||||
|
||||
The [`data`](#22-data) byte-sequence is used as the message body.
|
||||
|
||||
#### 3.1.2 Metadata Headers
|
||||
|
||||
All [CloudEvents][ce] attributes, including extensions, MUST be individually
|
||||
mapped to and from distinct NATS message header.
|
||||
|
||||
CloudEvents extensions that define their own attributes MAY define a secondary
|
||||
mapping to NATS headers for those attributes, especially if specific attributes
|
||||
need to align with NATS features or with other specifications that have explicit
|
||||
NATS header bindings. Note that these attributes MUST also still appear in the
|
||||
NATS message as NATS headers with the `ce-` prefix as noted in
|
||||
[NATS Header Names](#3131-nats-header-names).
|
||||
|
||||
##### 3.1.3.1 NATS Header Names
|
||||
|
||||
Except where noted, all CloudEvents context attributes, including extensions,
|
||||
MUST be mapped to NATS headers with the same name as the attribute name but
|
||||
prefixed with `ce-`.
|
||||
|
||||
Examples:
|
||||
|
||||
* `time` maps to `ce-time`
|
||||
* `id` maps to `ce-id`
|
||||
* `specversion` maps to `ce-specversion`
|
||||
* `datacontenttype` maps to `ce-datacontenttype`
|
||||
|
||||
Note: per the [NATS][nats-message-headers] design specification, header names are
|
||||
case-insensitive.
|
||||
|
||||
##### 3.1.3.2 NATS Header Values
|
||||
|
||||
The value for each NATS header is constructed from the respective attribute
|
||||
type's [canonical string representation][ce-types].
|
||||
|
||||
Some CloudEvents metadata attributes can contain arbitrary UTF-8 string content,
|
||||
and per [RFC7230, section 3][rfc7230-section-3], NATS headers MUST only use
|
||||
printable characters from the US-ASCII character set, and are terminated by a
|
||||
CRLF sequence with OPTIONAL whitespace around the header value.
|
||||
|
||||
When encoding a CloudEvent as an NATS message, string values
|
||||
represented as NATS header values MUST be percent-encoded as
|
||||
described below. This is compatible with [RFC3986, section
|
||||
2.1][rfc3986-section-2-1] but is more specific about what needs
|
||||
encoding. The resulting string SHOULD NOT be further encoded.
|
||||
(Rationale: quoted string escaping is unnecessary when every space
|
||||
and double-quote character is already percent-encoded.)
|
||||
|
||||
When decoding an NATS message into a CloudEvent, any NATS header
|
||||
value MUST first be unescaped with respect to double-quoted strings,
|
||||
as described in [RFC7230, section 3.2.6][rfc7230-section-3-2-6]. A single
|
||||
round of percent-decoding MUST then be performed as described
|
||||
below. NATS headers for CloudEvent attribute values do not support
|
||||
parenthetical comments, so the initial unescaping only needs to handle
|
||||
double-quoted values, including processing backslash escapes within
|
||||
double-quoted values. Header values produced via the
|
||||
percent-encoding described here will never include double-quoted
|
||||
values, but they MUST be supported when receiving events, for
|
||||
compatibility with older versions of this specification which did
|
||||
not require double-quote and space characters to be percent-encoded.
|
||||
|
||||
Percent encoding is performed by considering each Unicode character
|
||||
within the attribute's canonical string representation. Any
|
||||
character represented in memory as a [Unicode surrogate
|
||||
pair][surrogate-pair] MUST be treated as a single Unicode character.
|
||||
The following characters MUST be percent-encoded:
|
||||
|
||||
- Space (U+0020)
|
||||
- Double-quote (U+0022)
|
||||
- Percent (U+0025)
|
||||
- Any characters outside the printable ASCII range of U+0021-U+007E
|
||||
inclusive
|
||||
|
||||
Attribute values are already constrained to prohibit characters in
|
||||
the range U+0000-U+001F inclusive and U+007F-U+009F inclusive;
|
||||
however for simplicity and to account for potential future changes,
|
||||
it is RECOMMENDED that any NATS header encoding implementation treats
|
||||
such characters as requiring percent-encoding.
|
||||
|
||||
Space and double-quote are encoded to avoid requiring any further
|
||||
quoting. Percent is encoded to avoid ambiguity with percent-encoding
|
||||
itself.
|
||||
|
||||
Steps to encode a Unicode character:
|
||||
|
||||
- Encode the character using UTF-8, to obtain a byte sequence.
|
||||
- Encode each byte within the sequence as `%xy` where `x` is a
|
||||
hexadecimal representation of the most significant 4 bits of the byte,
|
||||
and `y` is a hexadecimal representation of the least significant 4
|
||||
bits of the byte.
|
||||
|
||||
Percent-encoding SHOULD be performed using upper-case for values A-F,
|
||||
but decoding MUST accept lower-case values.
|
||||
|
||||
When performing percent-decoding (when decoding an NATS message to a
|
||||
CloudEvent), values that have been unnecessarily percent-encoded MUST be
|
||||
accepted, but encoded byte sequences which are invalid in UTF-8 MUST be
|
||||
rejected. (For example, "%C0%A0" is an overlong encoding of U+0020, and
|
||||
MUST be rejected.)
|
||||
|
||||
Example: a header value of "Euro € 😀" SHOULD be encoded as follows:
|
||||
|
||||
- The characters, 'E', 'u', 'r', 'o' do not require encoding
|
||||
- Space, the Euro symbol, and the grinning face emoji require encoding.
|
||||
They are characters U+0020, U+20AC and U+1F600 respectively.
|
||||
- The encoded NATS header value is therefore "Euro%20%E2%82%AC%20%F0%9F%98%80"
|
||||
where "%20" is the encoded form of space, "%E2%82%AC" is the encoded form
|
||||
of the Euro symbol, and "%F0%9F%98%80" is the encoded form of the
|
||||
grinning face emoji.
|
||||
|
||||
#### 3.1.4 Example
|
||||
|
||||
This example shows the _binary_ mode mapping of an event in client messages that
|
||||
are [produced][nats-pub-proto] and [consumed][nats-msg-proto].
|
||||
|
||||
```text
|
||||
------------------ Message -------------------
|
||||
|
||||
Subject: mySubject
|
||||
|
||||
------------------ header --------------------
|
||||
|
||||
ce-specversion: 1.0
|
||||
ce-type: com.example.someevent
|
||||
ce-time: 2018-04-05T03:56:24Z
|
||||
ce-id: 1234-1234-1234
|
||||
ce-source: /mycontext/subcontext
|
||||
ce-datacontenttype: application/json
|
||||
|
||||
|
||||
------------------ payload -------------------
|
||||
|
||||
{
|
||||
... application data ...
|
||||
}
|
||||
|
||||
-----------------------------------------------
|
||||
```
|
||||
|
||||
### 3.2 Structured Content Mode
|
||||
|
||||
The chosen [event format](#14-event-formats) defines how all attributes,
|
||||
including the payload, are represented.
|
||||
|
||||
The event metadata and data MUST then be rendered in accordance with the event
|
||||
format specification and the resulting data becomes the payload.
|
||||
|
||||
### 3.2.1 Example
|
||||
|
||||
This example shows a JSON event format encoded event in client messages that are
|
||||
[produced][nats-pub-proto] and [consumed][nats-msg-proto].
|
||||
|
||||
```text
|
||||
------------------ Message -------------------
|
||||
|
||||
Subject: mySubject
|
||||
|
||||
------------------ payload -------------------
|
||||
|
||||
{
|
||||
"specversion" : "1.0",
|
||||
"type" : "com.example.someevent",
|
||||
|
||||
... further attributes omitted ...
|
||||
|
||||
"data" : {
|
||||
... application data ...
|
||||
}
|
||||
}
|
||||
|
||||
-----------------------------------------------
|
||||
```
|
||||
|
||||
## 4. References
|
||||
|
||||
- [NATS][nats] The NATS Messaging System
|
||||
- [NATS-PUB-PROTO][nats-pub-proto] The NATS protocol for messages published by a
|
||||
client
|
||||
- [NATS-MSG-PROTO][nats-msg-proto] The NATS protocol for messages received by a
|
||||
client
|
||||
- [RFC2046][rfc2046] Multipurpose Internet Mail Extensions (MIME) Part Two:
|
||||
Media Types
|
||||
- [RFC2119][rfc2119] Key words for use in RFCs to Indicate Requirement Levels
|
||||
- [RFC3629][rfc3629] UTF-8, a transformation format of ISO 10646
|
||||
- [RFC7159][rfc7159] The JavaScript Object Notation (JSON) Data Interchange
|
||||
Format
|
||||
|
||||
[ce]: ../spec.md
|
||||
[ce-types]: ../spec.md#type-system
|
||||
[json-format]: ../formats/json-format.md
|
||||
[json-value]: https://tools.ietf.org/html/rfc7159#section-3
|
||||
[nats]: https://nats.io
|
||||
[nats22]: https://docs.nats.io/release-notes/whats_new/whats_new_22#message-headers
|
||||
[nats-message-headers]: https://github.com/nats-io/nats-architecture-and-design/blob/main/adr/ADR-4.md#nats-message-headers
|
||||
[nats-msg-proto]: https://docs.nats.io/reference/reference-protocols/nats-protocol#protocol-messages
|
||||
[nats-pub-proto]: https://docs.nats.io/reference/reference-protocols/nats-protocol#pub
|
||||
[rfc2046]: https://tools.ietf.org/html/rfc2046
|
||||
[rfc2119]: https://tools.ietf.org/html/rfc2119
|
||||
[rfc3629]: https://tools.ietf.org/html/rfc3629
|
||||
[rfc3986-section-2-1]: https://tools.ietf.org/html/rfc3986#section-2.1
|
||||
[rfc7159]: https://tools.ietf.org/html/rfc7159
|
||||
[rfc7230]: https://tools.ietf.org/html/rfc7230
|
||||
[rfc7230-section-3]: https://tools.ietf.org/html/rfc7230#section-3
|
||||
[rfc7230-section-3-2-6]: https://tools.ietf.org/html/rfc7230#section-3.2.6
|
||||
[surrogate-pair]: http://unicode.org/glossary/#surrogate_pair
|
|
@ -1,14 +1,10 @@
|
|||
# WebSockets Protocol Binding for CloudEvents - Version 1.0.1
|
||||
# WebSockets Protocol Binding for CloudEvents - Version 1.0.3-wip
|
||||
|
||||
## Abstract
|
||||
|
||||
The WebSockets Protocol Binding for CloudEvents defines how to establish and use
|
||||
full-duplex CloudEvents streams using [WebSockets][rfc6455].
|
||||
|
||||
## Status of this document
|
||||
|
||||
This document is a working draft.
|
||||
|
||||
## Table of Contents
|
||||
|
||||
1. [Introduction](#1-introduction)
|
||||
|
@ -57,8 +53,8 @@ format][ce-event-format].
|
|||
|
||||
### 1.3. Content Modes
|
||||
|
||||
The [CloudEvents specification][ce-message] defines two content modes for
|
||||
transferring events: _structured_ and _binary_.
|
||||
The [CloudEvents specification][ce-message] defines three content modes for
|
||||
transferring events: _structured_, _binary_ and _batch_.
|
||||
|
||||
Because of the nature of WebSockets messages, this specification supports only
|
||||
_structured_ data mode, hence event metadata attributes and event data are
|
||||
|
@ -154,15 +150,17 @@ format specification and the resulting data becomes the payload.
|
|||
- [RFC2119][rfc2119] Key words for use in RFCs to Indicate Requirement Levels
|
||||
- [RFC6455][rfc6455] The WebSocket Protocol
|
||||
|
||||
[ce]: ./spec.md
|
||||
[ce-message]: ./spec.md#message
|
||||
[ce-event-format]: ./spec.md#event-format
|
||||
[json-format]: ./json-format.md
|
||||
[json-batch-format]: ./json-format.md#4-json-batch-format
|
||||
[avro-format]: ./avro-format.md
|
||||
[proto-format]: ./protobuf-format.md
|
||||
[ce]: ../spec.md
|
||||
[ce-message]: ../spec.md#message
|
||||
[ce-event-format]: ../spec.md#event-format
|
||||
[json-format]: ../formats/json-format.md
|
||||
[json-batch-format]: ../formats/json-format.md#4-json-batch-format
|
||||
[avro-format]: ../formats/avro-format.md
|
||||
[proto-format]: ../formats/protobuf-format.md
|
||||
[rfc2119]: https://tools.ietf.org/html/rfc2119
|
||||
[rfc6455]: https://tools.ietf.org/html/rfc6455
|
||||
[rfc6455-section-1-3]: https://tools.ietf.org/html/rfc6455#section-1.3
|
||||
[rfc6455-section-4]: https://tools.ietf.org/html/rfc6455#section-4
|
||||
[rfc6455-section-1-9]: https://tools.ietf.org/html/rfc6455#section-1.9
|
||||
[rfc7230-section-5-1]: https://datatracker.ietf.org/doc/html/rfc7230#section-5.1
|
||||
[rfc6455-section-5-1]: https://datatracker.ietf.org/doc/html/rfc6455#section-5.1
|
|
@ -0,0 +1,55 @@
|
|||
# CloudEvents Extension Attributes
|
||||
|
||||
The [CloudEvents specification](../spec.md) defines a set of metadata
|
||||
attributes that can be used when transforming a generic event into a
|
||||
CloudEvent. The list of attributes specified in that document represent the
|
||||
minimal set that the specification authors deemed most likely to be used in a
|
||||
majority of situations.
|
||||
|
||||
This document defines some addition attributes that, while not as commonly used
|
||||
as the ones specified in the [CloudEvents specification](../spec.md), could
|
||||
still benefit from being formally specified in the hopes of providing some
|
||||
degree of interoperability. This also allows for attributes to be defined in an
|
||||
experimental manner and tested prior to being considered for inclusion in the
|
||||
[CloudEvents specification](../spec.md).
|
||||
|
||||
Implementations of the [CloudEvents specification](../spec.md) are not
|
||||
mandated to limit their use of extension attributes to just the ones specified
|
||||
in this document. The attributes defined in this document have no official
|
||||
standing and might be changed, or removed, at any time. As such, inclusion of
|
||||
an attribute in this document does not need to meet the same level of maturity,
|
||||
or popularity, as attributes defined in the
|
||||
[CloudEvents specification](../spec.md). To be
|
||||
included in this document, aside from the normal PR review process, the
|
||||
attribute needs to have at least two
|
||||
[Voting](../../docs/GOVERNANCE.md#membership) member organizations stating
|
||||
their support for its inclusion as comments in the PR. If the author of the PR
|
||||
is also a Voting member, then they are allowed to be one of two.
|
||||
|
||||
## Usage
|
||||
|
||||
Support for any extension is OPTIONAL. When an extension definition uses
|
||||
[RFC 2199](https://www.ietf.org/rfc/rfc2119.txt) keywords (e.g. MUST, SHOULD,
|
||||
MAY), this usage only applies to events that use the extension.
|
||||
|
||||
Extensions attributes, while not defined by the core CloudEvents specifications,
|
||||
MUST follow the same serialization rules as defined by the format and protocol
|
||||
binding specifications. See
|
||||
[Extension Context Attributes](../spec.md#extension-context-attributes)
|
||||
for more information.
|
||||
|
||||
## Known Extensions
|
||||
|
||||
- [Auth Context](authcontext.md)
|
||||
- [BAM](bam.md)
|
||||
- [Data Classification](data-classification.md)
|
||||
- [Dataref (Claim Check Pattern)](dataref.md)
|
||||
- [Deprecation](deprecation.md)
|
||||
- [Distributed Tracing](distributed-tracing.md)
|
||||
- [Expiry Time](expirytime.md)
|
||||
- [OPC UA](opcua.md)
|
||||
- [Partitioning](partitioning.md)
|
||||
- [Recorded Time](recordedtime.md)
|
||||
- [Sampling](sampledrate.md)
|
||||
- [Sequence](sequence.md)
|
||||
- [Severity](severity.md)
|
|
@ -0,0 +1,65 @@
|
|||
# Auth Context
|
||||
|
||||
This extension embeds information about the principal which triggered an
|
||||
occurrence. This allows consumers of the
|
||||
CloudEvent to perform user-dependent actions without requiring the user ID to
|
||||
be embedded in the `data` or `source` field.
|
||||
|
||||
This extension is purely informational and is not intended to secure
|
||||
CloudEvents.
|
||||
|
||||
## Notational Conventions
|
||||
|
||||
As with the main [CloudEvents specification](../spec.md), the key words "MUST",
|
||||
"MUST NOT", "REQUIRED", "SHALL", "SHALL NOT", "SHOULD", "SHOULD NOT",
|
||||
"RECOMMENDED", "MAY", and "OPTIONAL" in this document are to be interpreted as
|
||||
described in [RFC 2119](https://tools.ietf.org/html/rfc2119).
|
||||
|
||||
However, the scope of these key words is limited to when this extension is
|
||||
used. For example, an attribute being marked as "REQUIRED" does not mean
|
||||
it needs to be in all CloudEvents, rather it needs to be included only when
|
||||
this extension is being used.
|
||||
|
||||
## Attributes
|
||||
|
||||
### authtype
|
||||
- Type: `String`
|
||||
- Description: An enum representing the type of principal that triggered the
|
||||
occurrence. Valid values are:
|
||||
- `app_user`: An end user of an application. Examples include an AWS cognito,
|
||||
Google Cloud Identity Platform, or Azure Active Directory user.
|
||||
- `user`: A user account registered in the infrastructure. Examples include
|
||||
developer accounts secured by IAM in AWS, Google Cloud Platform, or Azure.
|
||||
- `service_account`: A non-user principal used to identify a service.
|
||||
- `api_key`: A non-user API key
|
||||
- `system`: An obscured identity used when a cloud platform or other system
|
||||
service triggers an event. Examples include a database record which
|
||||
was deleted based on a TTL.
|
||||
- `unauthenticated`: No credentials were used to authenticate the change that
|
||||
triggered the occurrence.
|
||||
- `unknown`: The type of principal cannot be determined and is unknown.
|
||||
- Constraints
|
||||
- REQUIRED
|
||||
- This specification defines the following values, and it is RECOMMENDED that
|
||||
they be used. However, implementations MAY define additional values.
|
||||
|
||||
### authid
|
||||
- Type: `String`
|
||||
- Description: A unique identifier of the principal that triggered the
|
||||
occurrence. This specification makes no statement as to what this value
|
||||
ought to be, however including personally identifiable information (PII)
|
||||
in a CloudEvent is often considered inappropriate, so some indirect reference
|
||||
(e.g. a hash or label of an API key) might be considered.
|
||||
- Constraints
|
||||
- OPTIONAL
|
||||
|
||||
### authclaims
|
||||
- Type: `String`
|
||||
- Description: A JSON string representing claims of the principal that triggered
|
||||
the event.
|
||||
- Constraints
|
||||
- OPTIONAL
|
||||
- MUST NOT contain actual credentials sufficient for the Consumer to
|
||||
impersonate the principal directly.
|
||||
- MAY contain enough information that a Consumer can authenticate against an
|
||||
identity service to mint a credential impersonating the original principal.
|
|
@ -0,0 +1,127 @@
|
|||
# Business Activity Monitoring (BAM) Extension
|
||||
|
||||
Business Activity Monitoring (BAM) was originally coined by analysts at
|
||||
Gartner, and refers to the aggregation, analysis, and presentation of
|
||||
real-time information about activities inside organizations, customers,
|
||||
and partners.
|
||||
|
||||
The activity monitoring consists of a model of a business process,
|
||||
which can consists of multiple transactions (e.g. order, payment, invoice),
|
||||
and these transactions can have multiple steps. The technical processing
|
||||
represented by a transaction instance `bamtxid` is then correlated with
|
||||
the steps in those transactions of the business process.
|
||||
|
||||
This extension defines attributes that can be included within a CloudEvent
|
||||
to describe the business activity that the event is associated with.
|
||||
|
||||
Producers and consumers are free to define an out-of-band agreement on the
|
||||
semantic meaning, or valid values, for the attribute.
|
||||
|
||||
## Notational Conventions
|
||||
|
||||
As with the main [CloudEvents specification](../spec.md), the key words "MUST",
|
||||
"MUST NOT", "REQUIRED", "SHALL", "SHALL NOT", "SHOULD", "SHOULD NOT",
|
||||
"RECOMMENDED", "MAY", and "OPTIONAL" in this document are to be interpreted as
|
||||
described in [RFC 2119](https://tools.ietf.org/html/rfc2119).
|
||||
|
||||
However, the scope of these key words is limited to when this extension is
|
||||
used. For example, an attribute being marked as "REQUIRED" does not mean
|
||||
it needs to be in all CloudEvents, rather it needs to be included only when
|
||||
this extension is being used.
|
||||
|
||||
## Attributes
|
||||
|
||||
### bamtxid (BAM Transaction ID)
|
||||
|
||||
- Type: `String`
|
||||
- Description: A unique identifier for the instance of a transaction.
|
||||
This identifier connects the actual processing in the distributed
|
||||
system (e.g. payment, invoice, warehouse) with the model of this process.
|
||||
- Constraints
|
||||
- REQUIRED
|
||||
- MUST be a non-empty string
|
||||
- RECOMMENDED as monotonically increasing and contiguous identifier
|
||||
that is lexicographically-sortable.
|
||||
|
||||
### bampid (BAM Process ID)
|
||||
|
||||
- Type: `String`
|
||||
- Description: A unique identifier for the model of the business process
|
||||
that is associated with instance of the transaction `bamtxid`.
|
||||
A business process is a collection of transactions. These transactions
|
||||
can run in sequence or parallel (e.g. payment, invoice, warehouse).
|
||||
- Constraints
|
||||
- REQUIRED
|
||||
- MUST be a non-empty string
|
||||
- RECOMMENDED an alphanumeric string that contains non-whitespace characters
|
||||
and only hyphens, underscores, and periods.
|
||||
|
||||
### bamptxid (BAM Process Transaction ID)
|
||||
|
||||
- Type: `String`
|
||||
- Description: A unique identifier for the model of a transaction that
|
||||
constructs a business process (e.g. payment, invoice, warehouse).
|
||||
- Constraints
|
||||
- REQUIRED
|
||||
- MUST be a non-empty string
|
||||
- RECOMMENDED an alphanumeric string that contains non-whitespace characters
|
||||
and only hyphens, underscores, and periods.
|
||||
|
||||
### bamptxsid (BAM Process Transaction Step ID)
|
||||
|
||||
- Type: `String`
|
||||
- Description: A unique identifier for the specific step in a business process
|
||||
transaction (e.g. start, processing, finish).
|
||||
- Constraints
|
||||
- REQUIRED
|
||||
- MUST be a non-empty string
|
||||
- RECOMMENDED an alphanumeric string that contains non-whitespace characters
|
||||
and only hyphens, underscores, and periods.
|
||||
|
||||
### bamptxsstatus (BAM Transaction Step Status)
|
||||
|
||||
- Type: `String`
|
||||
- Description: The status of the specific step in a business process
|
||||
transaction (e.g. success, waiting, failure).
|
||||
- Constraints
|
||||
- OPTIONAL
|
||||
- if present, MUST be a non-empty string
|
||||
- RECOMMENDED an alphanumeric string that contains non-whitespace characters
|
||||
and only hyphens, underscores, and periods.
|
||||
|
||||
### bamptxcompleted (BAM Process Transaction Completed)
|
||||
|
||||
- Type: `Boolean`
|
||||
- Description: Indicates if the instance of the transaction (`bamtxid`) has
|
||||
actually been completed, or if the transaction has somehow failed.
|
||||
This is a mechanism to indicate a final completion or failure that is
|
||||
not captured by the model of the business process.
|
||||
- Constraints
|
||||
- OPTIONAL
|
||||
- if present, MUST be a boolean value
|
||||
|
||||
## Usage
|
||||
|
||||
When this extension is used, producers MUST set the value of
|
||||
the `bamtxid`, `bampid`, `bamptxid`, and `bamptxsid` attributes
|
||||
to the unique identifiers of the business process, transaction,
|
||||
and transaction step associated with the event.
|
||||
|
||||
Intermediaries MUST NOT change the value of the `bamtxid`,
|
||||
`bampid`, `bamptxid`, and `bamptxsid` attributes.
|
||||
|
||||
## Use cases
|
||||
|
||||
This extension can be used in cases in which a business activity monitoring
|
||||
system is used to monitor the progress of a business process, and the events
|
||||
generated by the process are used to track the progress of the process.
|
||||
Usually these systems have their own modelling language to describe the
|
||||
business process, and the events generated by the process
|
||||
are used to track the progress of the process.
|
||||
|
||||
## References
|
||||
|
||||
- [Gartner Business Activity Monitoring](https://www.gartner.com/en/information-technology/glossary/bam-business-activity-monitoring)
|
||||
- [Business Activity Monitoring](https://en.wikipedia.org/wiki/Business_activity_monitoring)
|
||||
- [What is Business Activity Monitoring (BAM)?](https://www.ibm.com/topics/business-activity-monitoring)
|
||||
- [Business Activity Monitoring (BAM)](https://learn.microsoft.com/en-us/biztalk/core/business-activity-monitoring-bam)
|
|
@ -0,0 +1,228 @@
|
|||
# Correlation
|
||||
|
||||
This extension defines attributes for tracking occurrence relationships and
|
||||
causality in distributed systems, enabling comprehensive traceability through
|
||||
correlation and causation identifiers.
|
||||
|
||||
## Notational Conventions
|
||||
|
||||
As with the main [CloudEvents specification](../spec.md), the key words "MUST",
|
||||
"MUST NOT", "REQUIRED", "SHALL", "SHALL NOT", "SHOULD", "SHOULD NOT",
|
||||
"RECOMMENDED", "MAY", and "OPTIONAL" in this document are to be interpreted as
|
||||
described in [RFC 2119](https://tools.ietf.org/html/rfc2119).
|
||||
|
||||
## Attributes
|
||||
|
||||
### correlationid
|
||||
|
||||
- Type: `String`
|
||||
- Description: An identifier that groups related events within the same logical
|
||||
flow or business transaction. All events sharing the same correlation ID are
|
||||
part of the same workflow.
|
||||
- Constraints
|
||||
- OPTIONAL
|
||||
- If present, MUST be a non-empty string
|
||||
|
||||
### causationid
|
||||
|
||||
- Type: `String`
|
||||
- Description: The unique identifier of the event that directly caused this
|
||||
event to be generated. This SHOULD be the `id` value of the causing event.
|
||||
- Constraints
|
||||
- OPTIONAL
|
||||
- If present, MUST be a non-empty string
|
||||
|
||||
## Usage
|
||||
|
||||
The Correlation extension provides two complementary mechanisms for tracking
|
||||
event relationships:
|
||||
|
||||
1. **Correlation ID**: Groups all events that are part of the same logical flow,
|
||||
regardless of their causal relationships
|
||||
2. **Causation ID**: Tracks the direct parent-child relationships between events
|
||||
in a causal chain
|
||||
|
||||
These attributes can be used independently or together, depending on the correlation
|
||||
requirements of your system.
|
||||
|
||||
### Correlation vs Causation
|
||||
|
||||
Understanding the distinction between these two concepts is crucial:
|
||||
|
||||
- **Correlation ID** answers: "Which events are part of the same business
|
||||
transaction?"
|
||||
- **Causation ID** answers: "Which specific event directly triggered this
|
||||
event?"
|
||||
|
||||
### Example Scenario
|
||||
|
||||
Consider an e-commerce order processing flow:
|
||||
|
||||
1. User initiates checkout (correlation ID: "txn-abc-123" is created)
|
||||
2. Order is placed (Event A)
|
||||
3. Payment is processed (Event B, caused by A)
|
||||
4. Inventory is checked (Event C, caused by A)
|
||||
5. Shipping is scheduled (Event D, caused by C)
|
||||
6. Notification is sent (Event E, caused by D)
|
||||
|
||||
In this scenario:
|
||||
|
||||
- All events share the same `correlationid`: "txn-abc-123"
|
||||
- Each event has a `causationid` pointing to its direct trigger:
|
||||
- Event B and C have `causationid`: "order-123" (Event A's ID)
|
||||
- Event D has `causationid`: "inventory-456" (Event C's ID)
|
||||
- Event E has `causationid`: "shipping-789" (Event D's ID)
|
||||
|
||||
## Examples
|
||||
|
||||
### Example 1: Complete Correlation Chain
|
||||
|
||||
Initial Order Event:
|
||||
|
||||
```json
|
||||
{
|
||||
"specversion": "1.0",
|
||||
"type": "com.example.order.placed",
|
||||
"source": "https://example.com/orders",
|
||||
"id": "order-123",
|
||||
"correlationid": "txn-abc-123",
|
||||
"data": {
|
||||
"orderId": "123",
|
||||
"customerId": "456"
|
||||
}
|
||||
}
|
||||
```
|
||||
|
||||
Payment Processing (triggered by order):
|
||||
|
||||
```json
|
||||
{
|
||||
"specversion": "1.0",
|
||||
"type": "com.example.payment.processed",
|
||||
"source": "https://example.com/payments",
|
||||
"id": "payment-789",
|
||||
"correlationid": "txn-abc-123",
|
||||
"causationid": "order-123",
|
||||
"data": {
|
||||
"amount": 150.0,
|
||||
"currency": "USD"
|
||||
}
|
||||
}
|
||||
```
|
||||
|
||||
Inventory Check (also triggered by order):
|
||||
|
||||
```json
|
||||
{
|
||||
"specversion": "1.0",
|
||||
"type": "com.example.inventory.checked",
|
||||
"source": "https://example.com/inventory",
|
||||
"id": "inventory-456",
|
||||
"correlationid": "txn-abc-123",
|
||||
"causationid": "order-123",
|
||||
"data": {
|
||||
"items": ["sku-001", "sku-002"],
|
||||
"available": true
|
||||
}
|
||||
}
|
||||
```
|
||||
|
||||
Shipping Scheduled (triggered by inventory check):
|
||||
|
||||
```json
|
||||
{
|
||||
"specversion": "1.0",
|
||||
"type": "com.example.shipping.scheduled",
|
||||
"source": "https://example.com/shipping",
|
||||
"id": "shipping-012",
|
||||
"correlationid": "txn-abc-123",
|
||||
"causationid": "inventory-456",
|
||||
"data": {
|
||||
"carrier": "FastShip",
|
||||
"estimatedDelivery": "2024-01-15"
|
||||
}
|
||||
}
|
||||
```
|
||||
|
||||
### Example 2: Error Handling with Correlation
|
||||
|
||||
When an error occurs, the correlation attributes help identify both the affected
|
||||
transaction and the specific trigger:
|
||||
|
||||
```json
|
||||
{
|
||||
"specversion": "1.0",
|
||||
"type": "com.example.payment.failed",
|
||||
"source": "https://example.com/payments",
|
||||
"id": "error-345",
|
||||
"correlationid": "txn-abc-123",
|
||||
"causationid": "payment-789",
|
||||
"data": {
|
||||
"error": "Insufficient funds",
|
||||
"retryable": true
|
||||
}
|
||||
}
|
||||
```
|
||||
|
||||
### Example 3: Fan-out Pattern
|
||||
|
||||
A single event can cause multiple downstream events:
|
||||
|
||||
```json
|
||||
{
|
||||
"specversion": "1.0",
|
||||
"type": "com.example.order.fulfilled",
|
||||
"source": "https://example.com/fulfillment",
|
||||
"id": "fulfillment-567",
|
||||
"correlationid": "txn-abc-123",
|
||||
"causationid": "shipping-012",
|
||||
"data": {
|
||||
"completedAt": "2024-01-14T10:30:00Z"
|
||||
}
|
||||
}
|
||||
```
|
||||
|
||||
This might trigger multiple notification events, all with the same causationid:
|
||||
|
||||
```json
|
||||
{
|
||||
"specversion": "1.0",
|
||||
"type": "com.example.notification.email",
|
||||
"source": "https://example.com/notifications",
|
||||
"id": "notify-email-890",
|
||||
"correlationid": "txn-abc-123",
|
||||
"causationid": "fulfillment-567",
|
||||
"data": {
|
||||
"recipient": "customer@example.com",
|
||||
"template": "order-fulfilled"
|
||||
}
|
||||
}
|
||||
```
|
||||
|
||||
```json
|
||||
{
|
||||
"specversion": "1.0",
|
||||
"type": "com.example.notification.sms",
|
||||
"source": "https://example.com/notifications",
|
||||
"id": "notify-sms-891",
|
||||
"correlationid": "txn-abc-123",
|
||||
"causationid": "fulfillment-567",
|
||||
"data": {
|
||||
"recipient": "+1234567890",
|
||||
"message": "Your order has been fulfilled!"
|
||||
}
|
||||
}
|
||||
```
|
||||
|
||||
## Best Practices
|
||||
|
||||
1. **Correlation ID Generation**: Generate correlation IDs at the entry point of
|
||||
your system (e.g., API gateway, UI interaction)
|
||||
2. **Causation ID Propagation**: Always set the causation ID to the `id` of the
|
||||
event that directly triggered the current event
|
||||
3. **Consistent Usage**: If you start using these attributes in a flow, use them
|
||||
consistently throughout
|
||||
4. **ID Format**: Use globally unique identifiers (e.g., UUIDs) to avoid
|
||||
collisions across distributed systems
|
||||
5. **Retention**: Consider the retention implications when designing queries
|
||||
based on these attributes
|
|
@ -0,0 +1,110 @@
|
|||
# Data Classification Extension
|
||||
|
||||
CloudEvents might contain payloads which are subjected to data protection
|
||||
regulations like GDPR or HIPAA. For intermediaries and consumers knowing how
|
||||
event payloads are classified, which data protection regulation applies and how
|
||||
payloads are categorized, enables compliant processing of events.
|
||||
|
||||
This extension defines attributes to describe to
|
||||
[consumers](../spec.md#consumer) or [intermediaries](../spec.md#intermediary)
|
||||
how an event and its payload is classified, category of the payload and any
|
||||
applicable data protection regulations.
|
||||
|
||||
These attributes are intended for classification at an event and payload level
|
||||
and not at a `data` field level. Classification at a field level is best defined
|
||||
in the schema specified via the `dataschema` attribute.
|
||||
|
||||
## Notational Conventions
|
||||
|
||||
As with the main [CloudEvents specification](../spec.md), the key words "MUST",
|
||||
"MUST NOT", "REQUIRED", "SHALL", "SHALL NOT", "SHOULD", "SHOULD NOT",
|
||||
"RECOMMENDED", "MAY", and "OPTIONAL" in this document are to be interpreted as
|
||||
described in [RFC 2119](https://tools.ietf.org/html/rfc2119).
|
||||
|
||||
However, the scope of these key words is limited to when this extension is used.
|
||||
For example, an attribute being marked as "REQUIRED" does not mean it needs to
|
||||
be in all CloudEvents, rather it needs to be included only when this extension
|
||||
is being used.
|
||||
|
||||
## Attributes
|
||||
|
||||
### dataclassification
|
||||
|
||||
- Type: `String`
|
||||
- Description: Data classification level for the event payload within the
|
||||
context of a `dataregulation`. In situations where `dataregulation` is
|
||||
undefined or the data protection regulation does not define any labels, then
|
||||
RECOMMENDED labels are: `public`, `internal`, `confidential`, or
|
||||
`restricted`.
|
||||
- Constraints:
|
||||
- REQUIRED
|
||||
|
||||
### dataregulation
|
||||
|
||||
- Type: `String`
|
||||
- Description: A comma-delimited list of applicable data protection regulations.
|
||||
For example: `GDPR`, `HIPAA`, `PCI-DSS`, `ISO-27001`, `NIST-800-53`, `CCPA`.
|
||||
- Constraints:
|
||||
- OPTIONAL
|
||||
- if present, MUST be a non-empty string without internal spaces. Leading and
|
||||
trailing spaces around each entry MUST be ignored.
|
||||
|
||||
### datacategory
|
||||
|
||||
- Type: `String`
|
||||
- Description: Data category of the event payload within the context of a
|
||||
`dataregulation` and `dataclassification`. For GDPR personal data typical
|
||||
labels are: `non-sensitive`, `standard`, `sensitive`, `special-category`. For
|
||||
US personal data this could be: `sensitive-pii`, `non-sensitive-pii`,
|
||||
`non-pii`. And for personal health information under HIPAA: `phi`.
|
||||
- Constraints:
|
||||
- OPTIONAL
|
||||
- if present, MUST be a non-empty string
|
||||
|
||||
## Usage
|
||||
|
||||
When this extension is used, producers MUST set the value of the
|
||||
`dataclassification` attribute. When applicable the `dataregulation` and
|
||||
`datacategory` attributes MAY be set to provide additional details on the
|
||||
classification context.
|
||||
|
||||
When an implementation supports this extension, then intermediaries and
|
||||
consumers MUST take these attributes into account and act accordingly to data
|
||||
regulations and/or internal policies in processing the event and payload. If
|
||||
intermediaries or consumers cannot meet such requirements, they MUST reject and
|
||||
report an error through a protocol-level mechanism.
|
||||
|
||||
If intermediaries or consumers are unsure on how to interpret these attributes,
|
||||
for example when they encounter an unknown classification level or data
|
||||
regulation, they MUST assume they cannot meet requirements and MUST reject the
|
||||
event and report an error through a protocol-level mechanism.
|
||||
|
||||
Intermediaries SHOULD NOT modify the `dataclassification`, `dataregulation`, and
|
||||
`datacategory` attributes.
|
||||
|
||||
## Use cases
|
||||
|
||||
Examples where data classification of events can be useful are:
|
||||
|
||||
- When an event contains PII or restricted information and therefore processing
|
||||
by intermediaries or consumers need to adhere to certain policies. For example
|
||||
having separate processing pipelines by sensitivity or having logging,
|
||||
auditing and access policies based upon classification.
|
||||
- When an event payload is subjected to regulation and therefore retention
|
||||
policies apply. For example, having event retention policies based upon data
|
||||
classification or to enable automated data purging of durable topics.
|
||||
|
||||
## Appendix: Data Protection and Privacy Regulations
|
||||
|
||||
For reference purposes, a catalog of common data protection and privacy
|
||||
regulation and abbreviations is availble from [UNCTAD
|
||||
(United Nations Conference on Trade and
|
||||
Development)](https://unctad.org/page/data-protection-and-privacy-legislation-worldwide),
|
||||
under the `DOWNLOAD FULL DATA` button ([direct
|
||||
link](https://unctad.org/system/files/information-document/DP.xlsx)). Others
|
||||
might exist.
|
||||
|
||||
Some examples include:
|
||||
- `GDPR` - General Data Protection Regulation, Europe
|
||||
- `HIPAA` - Health Insurance Portability and Accountability Act, United States
|
||||
- `NDPR` - Nigeria Data Protection Regulation, Nigeria
|
|
@ -10,7 +10,25 @@ MUST be identical.
|
|||
Both `data` and the `dataref` attribute MAY exist at the same time. A middleware
|
||||
MAY drop `data` when the `dataref` attribute exists, it MAY add
|
||||
the `dataref` attribute and drop the `data` attribute, or it MAY add the `data`
|
||||
attribute by using the `dataref` attribute.
|
||||
attribute by using the `dataref` attribute. Note that since the CloudEvents
|
||||
specification does not define a mechanism by which a sender can know if the
|
||||
receiver supports any particular CloudEvent extension, removing the `data`
|
||||
attribute in favor of just having the `dataref` attribute could yield
|
||||
unexpected results. As such, removing the `data` attribute SHOULD only be done
|
||||
when the sender is confident that all receivers support the `dataref`
|
||||
attribute - via some out-of-band agreement.
|
||||
|
||||
## Notational Conventions
|
||||
|
||||
As with the main [CloudEvents specification](../spec.md), the key words "MUST",
|
||||
"MUST NOT", "REQUIRED", "SHALL", "SHALL NOT", "SHOULD", "SHOULD NOT",
|
||||
"RECOMMENDED", "MAY", and "OPTIONAL" in this document are to be interpreted as
|
||||
described in [RFC 2119](https://tools.ietf.org/html/rfc2119).
|
||||
|
||||
However, the scope of these key words is limited to when this extension is
|
||||
used. For example, an attribute being marked as "REQUIRED" does not mean
|
||||
it needs to be in all CloudEvents, rather it needs to be included only when
|
||||
this extension is being used.
|
||||
|
||||
## Attributes
|
||||
|
||||
|
@ -24,22 +42,22 @@ attribute by using the `dataref` attribute.
|
|||
Known as the "Claim Check Pattern", this attribute MAY be used for a variety
|
||||
of purposes, including:
|
||||
|
||||
- If the [Data](../spec.md#data) is too large to be included in the message,
|
||||
the `data` is not present, and the consumer can retrieve it using
|
||||
- If the [Data](../spec.md#data) is too large to be included in the
|
||||
message, the `data` is not present, and the consumer can retrieve it using
|
||||
this attribute.
|
||||
- If the consumer wants to verify that the [Data](../spec.md#data) has not
|
||||
been tampered with, it can retrieve it from a trusted source using this
|
||||
attribute.
|
||||
- If the [Data](../spec.md#data) MUST only be viewed by trusted consumers
|
||||
(e.g. personally identifiable information), only a trusted consumer can
|
||||
retrieve it using this attribute and a pre-shared secret.
|
||||
- If the consumer wants to verify that the [Data](../spec.md#data)
|
||||
has not been tampered with, it can retrieve it from a trusted source using
|
||||
this attribute.
|
||||
- If the [Data](../spec.md#data) MUST only be viewed by trusted
|
||||
consumers (e.g. personally identifiable information), only a trusted
|
||||
consumer can retrieve it using this attribute and a pre-shared secret.
|
||||
|
||||
If this attribute is used, the information SHOULD be accessible long enough
|
||||
for all consumers to retrieve it, but MAY not be stored for an extended period
|
||||
of time.
|
||||
|
||||
- Constraints:
|
||||
- OPTIONAL
|
||||
- REQUIRED
|
||||
|
||||
# Examples
|
||||
|
|
@ -0,0 +1,86 @@
|
|||
# Deprecation extension
|
||||
|
||||
This specification defines attributes that can be included in CloudEvents to
|
||||
indicate to [consumers](../spec.md#consumer) or
|
||||
[intermediaries](../spec.md#intermediary) the deprecation of events. These
|
||||
attributes inform CloudEvents consumers about upcoming changes or removals,
|
||||
facilitating smoother transitions and proactive adjustments.
|
||||
|
||||
## Notational Conventions
|
||||
|
||||
As with the main [CloudEvents specification](../spec.md), the key words "MUST",
|
||||
"MUST NOT", "REQUIRED", "SHALL", "SHALL NOT", "SHOULD", "SHOULD NOT",
|
||||
"RECOMMENDED", "MAY", and "OPTIONAL" in this document are to be interpreted as
|
||||
described in [RFC 2119](https://tools.ietf.org/html/rfc2119).
|
||||
|
||||
However, the scope of these key words is limited to when this extension is
|
||||
used. For example, an attribute being marked as "REQUIRED" does not mean it
|
||||
needs to be in all CloudEvents, rather it needs to be included only when this
|
||||
extension is being used.
|
||||
|
||||
## Attributes
|
||||
|
||||
### deprecated
|
||||
|
||||
- Type: `Boolean`
|
||||
- Description: Indicates whether the event type is deprecated.
|
||||
- Constraints
|
||||
- MUST be `true`
|
||||
- REQUIRED
|
||||
- Example: `"deprecated": true`
|
||||
|
||||
### deprecationfrom
|
||||
|
||||
- Type: `Timestamp`
|
||||
- Description: Specifies the date and time when the event type was
|
||||
officially marked as deprecated.
|
||||
- Constraints
|
||||
- OPTIONAL
|
||||
- The `deprecationfrom` timestamp SHOULD remain stable once set and SHOULD
|
||||
reflect a point in the past or present. Pre-announcing deprecation by
|
||||
setting a future date is not encouraged.
|
||||
- Example: `"deprecationfrom": "2024-10-11T00:00:00Z"`
|
||||
|
||||
### deprecationsunset
|
||||
|
||||
- Type: `Timestamp`
|
||||
- Description: Specifies the future date and time when the event type will
|
||||
become unsupported.
|
||||
- Constraints
|
||||
- OPTIONAL
|
||||
- The timestamp MUST be later than or the same as the one given in the
|
||||
`deprecationfrom` field, if present. It MAY be extended to a later date but
|
||||
MUST NOT be shortened once set.
|
||||
- Example: `"deprecationsunset": "2024-11-12T00:00:00Z"`
|
||||
|
||||
### deprecationmigration
|
||||
|
||||
- Type: `URI`
|
||||
- Description: Provides a link to documentation or resources that describe
|
||||
the migration path from the deprecated event to an alternative. This helps
|
||||
consumers transition away from the deprecated event.
|
||||
- Constraints
|
||||
- OPTIONAL
|
||||
- The URI SHOULD point to a valid and accessible resource that helps
|
||||
consumers understand what SHOULD replace the deprecated event.
|
||||
- Example: `"deprecationmigration": "https://example.com/migrate-to-new-evt"`
|
||||
|
||||
## Usage
|
||||
|
||||
When this extension is used, producers MUST set the value of the `deprecated`
|
||||
attribute to `true`. This gives consumers a heads-up that they SHOULD begin
|
||||
migrating to a new event or version.
|
||||
|
||||
Consumers SHOULD make efforts to switch to the suggested replacement before the
|
||||
specified `deprecationsunset` timestamp. It is advisable to begin transitioning
|
||||
as soon as the event is marked as deprecated to ensure a smooth migration and
|
||||
avoid potential disruptions after the sunset date.
|
||||
|
||||
If an event is received after the `deprecationsunset` timestamp, consumers
|
||||
SHOULD choose to stop processing such events, especially if unsupported events
|
||||
can cause downstream issues.
|
||||
|
||||
Producers SHOULD stop emitting deprecated events after the `deprecationsunset`
|
||||
timestamp. They SHOULD also provide detailed documentation via the
|
||||
`deprecationmigration` attribute to guide consumers toward the correct replacement
|
||||
event.
|
|
@ -0,0 +1,89 @@
|
|||
# Distributed Tracing extension
|
||||
|
||||
This extension embeds context from
|
||||
[W3C TraceContext](https://www.w3.org/TR/trace-context/) into a CloudEvent.
|
||||
The goal of this extension is to offer means to carry context when instrumenting
|
||||
CloudEvents based systems with OpenTelemetry.
|
||||
|
||||
The [OpenTelemetry](https://opentelemetry.io/) project is a collection
|
||||
of tools, APIs and SDKs that can be used to instrument, generate, collect,
|
||||
and export telemetry data (metrics, logs, and traces) to help you
|
||||
analyze your software’s performance and behavior.
|
||||
|
||||
The OpenTelemetry specification defines both
|
||||
[Context](https://github.com/open-telemetry/opentelemetry-specification/blob/v1.8.0/specification/context/context.md#overview)
|
||||
and
|
||||
[Distributed Tracing](https://github.com/open-telemetry/opentelemetry-specification/blob/v1.8.0/specification/overview.md#tracing-signal)
|
||||
as:
|
||||
|
||||
> A `Context` is a propagation mechanism which carries execution-scoped values across
|
||||
API boundaries and between logically associated execution units. Cross-cutting
|
||||
concerns access their data in-process using the same shared `Context` object.
|
||||
>
|
||||
> A `Distributed Trace` is a set of events, triggered as a result of a single
|
||||
logical operation, consolidated across various components of an application.
|
||||
A distributed trace contains events that cross process, network and security boundaries.
|
||||
|
||||
## Notational Conventions
|
||||
|
||||
As with the main [CloudEvents specification](../spec.md), the key words "MUST",
|
||||
"MUST NOT", "REQUIRED", "SHALL", "SHALL NOT", "SHOULD", "SHOULD NOT",
|
||||
"RECOMMENDED", "MAY", and "OPTIONAL" in this document are to be interpreted as
|
||||
described in [RFC 2119](https://tools.ietf.org/html/rfc2119).
|
||||
|
||||
However, the scope of these key words is limited to when this extension is
|
||||
used. For example, an attribute being marked as "REQUIRED" does not mean
|
||||
it needs to be in all CloudEvents, rather it needs to be included only when
|
||||
this extension is being used.
|
||||
|
||||
## Attributes
|
||||
|
||||
### traceparent
|
||||
|
||||
- Type: `String`
|
||||
- Description: Contains a version, trace ID, span ID, and trace options as
|
||||
defined in [section 3.2](https://w3c.github.io/trace-context/#traceparent-header)
|
||||
- Constraints
|
||||
- REQUIRED
|
||||
|
||||
### tracestate
|
||||
|
||||
- Type: `String`
|
||||
- Description: a comma-delimited list of key-value pairs, defined by
|
||||
[section 3.3](https://w3c.github.io/trace-context/#tracestate-header).
|
||||
- Constraints
|
||||
- OPTIONAL
|
||||
|
||||
## Using the Distributed Tracing Extension
|
||||
|
||||
The Distributed Tracing Extension is not intended to replace the protocol specific headers for tracing,
|
||||
like the ones described in [W3C Trace Context](https://w3c.github.io/trace-context/) for HTTP.
|
||||
|
||||
Given a single hop event transmission (from source to sink directly), the Distributed Tracing Extension,
|
||||
if used, MUST carry the same trace information contained in protocol specific tracing headers.
|
||||
|
||||
Given a multi hop event transmission, the Distributed Tracing Extension, if used, MUST
|
||||
carry the trace information of the starting trace of the transmission.
|
||||
In other words, it MUST NOT carry trace information of each individual hop, since this information is usually
|
||||
carried using protocol specific headers, understood by tools like [OpenTelemetry](https://opentelemetry.io/).
|
||||
|
||||
The
|
||||
[OpenTelemetry Semantic Conventions for CloudEvents](https://opentelemetry.io/docs/specs/semconv/cloudevents/cloudevents-spans/)
|
||||
define the trace structure to follow when instrumenting CloudEvent systems and
|
||||
in which scenarios this extension can be used and how to use it to achieve said structure.
|
||||
|
||||
Middleware between the source and the sink of the event could eventually add a Distributed Tracing Extension
|
||||
if the source didn't include any, in order to provide to the sink the starting trace of the transmission.
|
||||
|
||||
An example with HTTP:
|
||||
|
||||
```bash
|
||||
CURL -X POST example/webhook.json \
|
||||
-H 'ce-id: 1' \
|
||||
-H 'ce-specversion: 1.0' \
|
||||
-H 'ce-type: example' \
|
||||
-H 'ce-source: http://localhost' \
|
||||
-H 'ce-traceparent: 00-0af7651916cd43dd8448eb211c80319c-b9c7c989f97918e1-01' \
|
||||
-H 'traceparent: 00-4bf92f3577b34da6a3ce929d0e0e4736-00f067aa0ba902b7-01' \
|
||||
-H 'tracestate: rojo=00-4bf92f3577b34da6a3ce929d0e0e4736-00f067aa0ba902b7-01,congo=lZWRzIHRoNhcm5hbCBwbGVhc3VyZS4`
|
||||
```
|
|
@ -0,0 +1,69 @@
|
|||
# Expiry Time Extension
|
||||
|
||||
This extension provides a mechanism to hint to [consumers](../spec.md#consumer)
|
||||
or [intermediaries](../spec.md#intermediary) a timestamp after which an
|
||||
[event](../spec.md#event) can be ignored.
|
||||
|
||||
In distributed systems with message delivery guarantees, events might be delivered
|
||||
to a consumer some significant amount of time after an event has been sent.
|
||||
In this situation, it might be desirable to ignore events that
|
||||
are no longer relevant. The [`time` attribute](../spec.md#time) could be used
|
||||
to handle this on the consumer side but can be tricky if the logic varies
|
||||
depending on the event type or producer.
|
||||
|
||||
## Notational Conventions
|
||||
|
||||
As with the main [CloudEvents specification](../spec.md), the key words "MUST",
|
||||
"MUST NOT", "REQUIRED", "SHALL", "SHALL NOT", "SHOULD", "SHOULD NOT",
|
||||
"RECOMMENDED", "MAY", and "OPTIONAL" in this document are to be interpreted as
|
||||
described in [RFC 2119](https://tools.ietf.org/html/rfc2119).
|
||||
|
||||
However, the scope of these key words is limited to when this extension is
|
||||
used. For example, an attribute being marked as "REQUIRED" does not mean
|
||||
it needs to be in all CloudEvents, rather it needs to be included only when
|
||||
this extension is being used.
|
||||
|
||||
## Attributes
|
||||
|
||||
### expirytime
|
||||
|
||||
- Type: `Timestamp`
|
||||
- Description: Timestamp indicating an event is no longer useful after the
|
||||
indicated time.
|
||||
- Constraints:
|
||||
- REQUIRED
|
||||
- SHOULD be equal to or later than the `time` attribute, if present
|
||||
|
||||
## Usage
|
||||
|
||||
When this extension is used, producers MUST set the value of the `expirytime`
|
||||
attribute.
|
||||
|
||||
Intermediaries and consumers MAY ignore and discard an event that has an
|
||||
`expirytime` at or before the current timestamp at the time of any checks.
|
||||
Any system that directly or indirectly interacts with a consumer SHOULD NOT
|
||||
make any assumptions on whether a consumer will
|
||||
keep or discard an event based on this extension alone. The reasoning for this
|
||||
is that time-keeping can be inaccurate between any two given systems.
|
||||
|
||||
Intermediaries MAY modify the `expirytime` attribute, however, they MUST NOT
|
||||
remove it.
|
||||
|
||||
## Potential Scenarios
|
||||
|
||||
### Web dashboard for sensors
|
||||
|
||||
A series of sensors produce CloudEvents at regular intervals that vary per
|
||||
sensor. Each sensor can pick an `expirytime` that suits its configured sample
|
||||
rate. In the event that an intermediary delays delivery of events to a
|
||||
consumer, older events can be skipped to avoid excessive processing or UI
|
||||
updates upon resuming delivery.
|
||||
|
||||
### Jobs triggered by Continuous Integration
|
||||
|
||||
A Continuous Integration (CI) system uses CloudEvents to delegate a job to a
|
||||
runner machine. The job has a set deadline and needs to complete before that time
|
||||
has elapsed to be considered successful. The CI system can set the
|
||||
`expirytime` to match the deadline. The job runner would ignore/reject the job
|
||||
if the `expirytime` has elapsed since the CI might have likely already determined
|
||||
the job state.
|
|
@ -0,0 +1,336 @@
|
|||
# OPC UA
|
||||
|
||||
This extension defines the mapping of [OPC UA](https://reference.opcfoundation.org/Core/Part1/v105/docs/)
|
||||
[PubSub](https://reference.opcfoundation.org/Core/Part14/v105/docs/) dataset to
|
||||
CloudEvents to allow seamless routing of OPC UA dataset messages via different
|
||||
protocols, it therefore provides a recommendation to map known REQUIRED and
|
||||
OPTIONAL attributes using other extensions as well as defines its own extension
|
||||
attributes.
|
||||
|
||||
## Notational Conventions
|
||||
|
||||
As with the main [CloudEvents specification](../spec.md), the key words "MUST",
|
||||
"MUST NOT", "REQUIRED", "SHALL", "SHALL NOT", "SHOULD", "SHOULD NOT",
|
||||
"RECOMMENDED", "MAY", and "OPTIONAL" in this document are to be interpreted as
|
||||
described in [RFC 2119](https://tools.ietf.org/html/rfc2119).
|
||||
|
||||
However, the scope of these key words is limited to when this extension is used.
|
||||
For example, an attribute being marked as "REQUIRED" does not mean it needs to
|
||||
be in all CloudEvents, rather it needs to be included only when this extension
|
||||
is being used.
|
||||
|
||||
## Mapping of REQUIRED Attributes
|
||||
|
||||
### id
|
||||
|
||||
MUST map to [Network Message
|
||||
Header](https://reference.opcfoundation.org/Core/Part14/v105/docs/7.2.5.3#Table163)
|
||||
field `MessageId`.
|
||||
|
||||
### source
|
||||
|
||||
MUST either map to [Application
|
||||
Description](https://reference.opcfoundation.org/Core/Part4/v104/docs/7.1) field
|
||||
`applicationUri` of the OPC UA server or to a customer configured identifier
|
||||
like a unified namespace path.
|
||||
|
||||
### type
|
||||
|
||||
MUST map to [Data Set Message Header](https://reference.opcfoundation.org/Core/Part14/v105/docs/7.2.5.4#Table164)
|
||||
field `MessageType`.
|
||||
|
||||
## Mapping of OPTIONAL Attributes
|
||||
|
||||
### datacontenttype
|
||||
|
||||
MUST be `application/json` for OPC UA PubSub JSON payload and MAY be appended with
|
||||
`+gzip` when the payload is gzip compressed.
|
||||
|
||||
### dataschema
|
||||
|
||||
OPC UA provides type information as part of PubSub metadata messages, for non
|
||||
OPC UA consumers or when different payload encoding like Avro is used, it is
|
||||
REQUIRED to provide schema information (based on metadata information) in a
|
||||
separate format like [JSON schema](https://json-schema.org/specification) or
|
||||
[Avro schema](https://avro.apache.org/docs/1.11.1/specification/) or others. For
|
||||
those cases the attribute references the schema and is used for versioning.
|
||||
|
||||
### subject
|
||||
|
||||
For metadata, event and data messages (type one of `ua-metadata`, `ua-keyframe`,
|
||||
`ua-deltaframe`, `ua-event`), `subject` MUST map to either [Data Set Message
|
||||
Header](https://reference.opcfoundation.org/Core/Part14/v105/docs/7.2.5.4#Table164)
|
||||
field `DataSetWriterId` or `DataSetWriterName`.
|
||||
|
||||
For event messages (type equals to `ua-event`) `subject` MUST be appended with
|
||||
"/" and [Base Event Type](https://reference.opcfoundation.org/Core/Part5/v104/docs/6.4.2)
|
||||
field `EventId`.
|
||||
|
||||
### time
|
||||
|
||||
MUST map to [Data Set Message
|
||||
Header](https://reference.opcfoundation.org/Core/Part14/v105/docs/7.2.5.4#Table164)
|
||||
field `Timestamp`.
|
||||
|
||||
## Mapping for other extensions
|
||||
|
||||
The following well-known extensions attributes MUST be used for data messages and
|
||||
event messages (type one of `ua-keyframe`, `ua-deltaframe`, `ua-event`).
|
||||
|
||||
### sequence
|
||||
|
||||
Attribute as defined by [sequence extensions](./sequence.md) MUST map to [Data
|
||||
Set Message Header](https://reference.opcfoundation.org/Core/Part14/v105/docs/7.2.5.4#Table164)
|
||||
field `SequenceNumber`.
|
||||
|
||||
### traceparent
|
||||
|
||||
Attribute as defined by [distributed-tracing extension](./distributed-tracing.md)
|
||||
to allow tracing from event publisher towards consumer.
|
||||
|
||||
### tracestate
|
||||
|
||||
Attribute as defined by [distributed-tracing extension](./distributed-tracing.md)
|
||||
MAY be used to allow tracing from event publisher towards consumer.
|
||||
|
||||
### recordedtime
|
||||
|
||||
Attribute as defined by [recordedtime extension](./recordedtime.md) to
|
||||
determine the latency between event publisher towards consumer.
|
||||
|
||||
## Attributes
|
||||
|
||||
### opcuametadatamajorversion
|
||||
|
||||
- Type: `Integer`
|
||||
- Description: Links dataset message to the current version of the metadata.
|
||||
Contains value from `MajorVersion` of [Data Set Message Header](https://reference.opcfoundation.org/Core/Part14/v105/docs/7.2.5.4#Table164) field `MetaDataVersion`.
|
||||
- Constraints
|
||||
- OPTIONAL but MUST NOT be present if `dataschema` is used
|
||||
|
||||
### opcuametadataminorversion
|
||||
|
||||
- Type: `Integer`
|
||||
- Description: Links dataset message to the current version of the metadata.
|
||||
Contains value from `MinorVersion` of [Data Set Message
|
||||
Header](https://reference.opcfoundation.org/Core/Part14/v105/docs/7.2.5.4#Table164)
|
||||
field `MetaDataVersion`.
|
||||
- Constraints
|
||||
- OPTIONAL but MUST NOT be present if `dataschema` is used
|
||||
|
||||
### opcuastatus
|
||||
|
||||
- Type: `Integer`
|
||||
- Description: Defines the overall status of the data set message, maps to
|
||||
[Data Set Message Header](https://reference.opcfoundation.org/Core/Part14/v105/docs/7.2.5.4#Table164) field `Status`.
|
||||
- Constraints
|
||||
- OPTIONAL
|
||||
- REQUIRED if status is not _Good_
|
||||
- MAY be omitted if status is _Good_
|
||||
|
||||
## General Constraints
|
||||
|
||||
- OPC UA messages MUST use `binary-mode` of CloudEvents.
|
||||
- OPC UA PubSub JSON messages MUST be encoded using non-reversible encoding as
|
||||
the decoding information is contained in metadata messages or by schema
|
||||
referenced via `dataschema` attribute.
|
||||
- Payload of OPC UA PubSub JSON messages MUST NOT contain Network Message Header
|
||||
and Data Set Header as that information is mapped into CloudEvents attributes.
|
||||
- OPC UA PubSub JSON messages MUST contain exactly one dataset message.
|
||||
|
||||
## Examples
|
||||
|
||||
### Metadata message
|
||||
|
||||
The metadata message helps Cloud applications to understand the semantics and
|
||||
structure of dataset messages.
|
||||
|
||||
```text
|
||||
------------------ PUBLISH -------------------
|
||||
|
||||
Topic Name: opcua/json/DataSetMetaData/publisher-on-ot-edge
|
||||
Content Type: application/json; charset=utf-8
|
||||
|
||||
------------- User Properties ----------------
|
||||
|
||||
specversion: 1.0
|
||||
type: ua-metadata
|
||||
time: 2024-03-28T21:56:24Z
|
||||
id: 1234-1234-1234
|
||||
source: urn:factory:aggregationserver:opcua
|
||||
datacontenttype: application/json; charset=utf-8
|
||||
subject: energy-consumption-asset
|
||||
.... further attributes ...
|
||||
|
||||
------------------ payload -------------------
|
||||
|
||||
{
|
||||
... application data (OPC UA PubSub metadata) ...
|
||||
"ConfigurationVersion": {
|
||||
"MajorVersion": 672338910,
|
||||
"MinorVersion": 672341762
|
||||
}
|
||||
...
|
||||
}
|
||||
|
||||
-----------------------------------------------
|
||||
```
|
||||
|
||||
### Telemetry message
|
||||
|
||||
The telemetry or data messages contain values of all OPC UA nodes that had
|
||||
changed in a given period of time (`ua-deltaframe`) or contain values for all
|
||||
OPC UA nodes that were monitored (`ua-keyframe`).
|
||||
The complete list of monitored OPC UA nodes as well as the related type
|
||||
information are defined in the metadata message. The attributes
|
||||
`opcuametadatamajorversion` and `opcuametadataminorversion` are used to
|
||||
reference the correct metadata message. The `ua-deltaframe` messages will be
|
||||
used for hot and/or cold path processing and `ua-keyframe` messages can
|
||||
additional be used to update last-known-value tables.
|
||||
|
||||
|
||||
```text
|
||||
------------------ PUBLISH -------------------
|
||||
|
||||
Topic Name: opcua/json/DataSetMessage/publisher-on-ot-edge
|
||||
Content Type: application/json; charset=utf-8
|
||||
|
||||
------------- User Properties ----------------
|
||||
|
||||
specversion: 1.0
|
||||
type: ua-deltaframe
|
||||
time: 2024-03-28T21:56:42Z
|
||||
id: 1235-1235-1235
|
||||
source: urn:factory:aggregationserver:opcua
|
||||
datacontenttype: application/json; charset=utf-8
|
||||
subject: energy-consumption-asset
|
||||
sequence: 7
|
||||
traceparent: 4bf92f3577b34da6a3ce929d0e0e4736-00f067aa0ba902b7-00000011
|
||||
recordedtime: 2024-03-28T21:56:43Z
|
||||
opcuametadatamajorversion: 672338910
|
||||
opcuametadataminorversion: 672341762
|
||||
.... further attributes ...
|
||||
|
||||
------------------ payload -------------------
|
||||
|
||||
{
|
||||
... application data
|
||||
(OPC UA PubSub JSON single dataset Message)...
|
||||
}
|
||||
|
||||
-----------------------------------------------
|
||||
```
|
||||
|
||||
#### OPC UA PubSub JSON single dataset Message
|
||||
|
||||
Using CloudEvents and model the OPC UA PubSub header information as CloudEvent
|
||||
attributes enables integration into various system (independent from used
|
||||
protocols) and simplifies the payload structure.
|
||||
|
||||
```text
|
||||
{
|
||||
"IsRunning": {
|
||||
"Value": true,
|
||||
"SourceTimestamp": "2024-03-29T07:31:19.555Z"
|
||||
},
|
||||
"EnergyConsumption": {
|
||||
"Value": 31
|
||||
"SourceTimestamp": "2024-03-29T07:31:37.546Z",
|
||||
"StatusCode": {
|
||||
"Code":1073741824,
|
||||
"Symbol":"Uncertain"
|
||||
}
|
||||
},
|
||||
"EnergyPeak": {
|
||||
"Value": 54
|
||||
"SourceTimestamp": "2024-03-29T07:31:06.978Z"
|
||||
},
|
||||
"EnergyLow": {
|
||||
"Value": 22
|
||||
"SourceTimestamp": "2024-03-29T07:31:17.582Z"
|
||||
}
|
||||
}
|
||||
|
||||
```
|
||||
|
||||
### Event message
|
||||
|
||||
The event message will contain a single event and the identifier of this event is
|
||||
added to the `subject` to allow routing it into different systems without parsing
|
||||
the payload. Events are routed for example in systems like Manufacturing Execution
|
||||
Systems (MES), Supervisory Control and Data Acquisition systems (SCADA),
|
||||
Alerting Systems or Operation Technology Operator Terminals (HMI Clients) and
|
||||
also in hot and/or cold path processing. The attributes
|
||||
`opcuametadatamajorversion` and `opcuametadataminorversion` are used to
|
||||
reference the correct metadata message.
|
||||
|
||||
```text
|
||||
------------------ PUBLISH -------------------
|
||||
|
||||
Topic Name: opcua/json/DataSetMessage/publisher-on-ot-edge
|
||||
Content Type: application/json; charset=utf-8
|
||||
|
||||
------------- User Properties ----------------
|
||||
|
||||
specversion: 1.0
|
||||
type: ua-event
|
||||
time: 2024-03-28T21:57:01Z
|
||||
id: 1236-1237-1238
|
||||
source: urn:factory:aggregationserver:opcua
|
||||
datacontenttype: application/json; charset=utf-8
|
||||
subject: energy-consumption-asset/444321
|
||||
sequence: 18
|
||||
traceparent: caffef3577b34da6a3ce929d0e0e4736-00f067aa0ba902b7-00000011
|
||||
recordedtime: 2024-03-28T21:57:01Z
|
||||
opcuametadatamajorversion: 672338910
|
||||
opcuametadataminorversion: 672341762
|
||||
.... further attributes ...
|
||||
|
||||
------------------ payload -------------------
|
||||
|
||||
{
|
||||
... application data
|
||||
(OPC UA PubSub JSON Single Event Message)...
|
||||
}
|
||||
|
||||
-----------------------------------------------
|
||||
```
|
||||
|
||||
### Telemetry message with different Encoding
|
||||
|
||||
One major benefit of CloudEvents for OPC UA is that it is possible to support
|
||||
other encoding and external schema, while keeping the same OPC UA information for
|
||||
routing.
|
||||
|
||||
The example below uses Avro binary encoded payload, with the corresponding schema
|
||||
referenced by `dataschema`. The `source` will be defined by an customer defined
|
||||
hierarchical path.
|
||||
|
||||
```text
|
||||
------------------ PUBLISH -------------------
|
||||
|
||||
Topic Name: bottling-company/amsterdam/FillingArea1/FillingLine9/Cell1/Conveyor
|
||||
Content Type: application/avro
|
||||
|
||||
------------- User Properties ----------------
|
||||
|
||||
specversion: 1.0
|
||||
type: ua-keyframe
|
||||
time: 2024-03-28T23:59:59Z
|
||||
id: 6235-7235-8235
|
||||
source: bottling-company/amsterdam/FillingArea1/FillingLine9/Cell1/Conveyor
|
||||
datacontenttype: application/avro
|
||||
subject: energy-consumption-asset
|
||||
dataschema: http://example.com/schemas/energy-consumption-asset/v1.8
|
||||
sequence: 3141
|
||||
traceparent: 22222f3577b34da6a3ce929d0e0e4736-00f067aa0ba902b7-00000011
|
||||
recordedtime: 2024-03-28T23:59:59Z
|
||||
.... further attributes ...
|
||||
|
||||
------------------ payload -------------------
|
||||
|
||||
... application data
|
||||
(OPC UA PubSub Single DataSet Message as AVRO binary)...
|
||||
|
||||
-----------------------------------------------
|
||||
```
|
|
@ -10,6 +10,18 @@ partitioning key can be used to determine which bucket each event goes into. The
|
|||
entity sending the events can ensure that events that need to be placed into the
|
||||
same bucket are done so by using the same partition key on those events.
|
||||
|
||||
## Notational Conventions
|
||||
|
||||
As with the main [CloudEvents specification](../spec.md), the key words "MUST",
|
||||
"MUST NOT", "REQUIRED", "SHALL", "SHALL NOT", "SHOULD", "SHOULD NOT",
|
||||
"RECOMMENDED", "MAY", and "OPTIONAL" in this document are to be interpreted as
|
||||
described in [RFC 2119](https://tools.ietf.org/html/rfc2119).
|
||||
|
||||
However, the scope of these key words is limited to when this extension is
|
||||
used. For example, an attribute being marked as "REQUIRED" does not mean
|
||||
it needs to be in all CloudEvents, rather it needs to be included only when
|
||||
this extension is being used.
|
||||
|
||||
## Attributes
|
||||
|
||||
### partitionkey
|
|
@ -0,0 +1,81 @@
|
|||
# Recorded Time Extension
|
||||
|
||||
This extension defines an attribute that represents the time when an
|
||||
[_occurrence_](../spec.md#occurrence)
|
||||
was recorded in a particular
|
||||
[_event_](../spec.md#event),
|
||||
which is the time when the CloudEvent was created by a producer.
|
||||
|
||||
This attribute is distinct from the [`time`
|
||||
attribute](https://github.com/cloudevents/spec/blob/main/cloudevents/spec.md#time),
|
||||
which, according to the CloudEvents specification, SHOULD be the time when the
|
||||
occurrence happened, if it can be determined.
|
||||
|
||||
This attribute makes it possible to represent
|
||||
[bitemporal](https://en.wikipedia.org/wiki/Bitemporal_modeling) data with
|
||||
CloudEvents so that, for every event, both of the following times can be known
|
||||
by consumers:
|
||||
|
||||
- _Occurrence time_: timestamp of when the occurrence recorded in the event
|
||||
happened, which corresponds to the `time` attribute.
|
||||
- _Recorded time_: the timestamp of when the occurrence was recorded in a
|
||||
specific CloudEvent instance, which is represented by this extension.
|
||||
|
||||
## Notational Conventions
|
||||
|
||||
As with the main [CloudEvents specification](../spec.md), the key words "MUST",
|
||||
"MUST NOT", "REQUIRED", "SHALL", "SHALL NOT", "SHOULD", "SHOULD NOT",
|
||||
"RECOMMENDED", "MAY", and "OPTIONAL" in this document are to be interpreted as
|
||||
described in [RFC 2119](https://tools.ietf.org/html/rfc2119).
|
||||
|
||||
However, the scope of these key words is limited to when this extension is
|
||||
used. For example, an attribute being marked as "REQUIRED" does not mean
|
||||
it needs to be in all CloudEvents, rather it needs to be included only when
|
||||
this extension is being used.
|
||||
|
||||
## Attributes
|
||||
|
||||
### recordedtime
|
||||
|
||||
- Type: `Timestamp`
|
||||
- Description: Timestamp of when the occurrence was recorded in this CloudEvent,
|
||||
i.e. when the CloudEvent was created by a producer.
|
||||
- Constraints:
|
||||
- REQUIRED
|
||||
- If present, MUST adhere to the format specified in
|
||||
[RFC 3339](https://tools.ietf.org/html/rfc3339)
|
||||
- SHOULD be equal to or later than the _occurrence time_.
|
||||
|
||||
## Usage
|
||||
|
||||
When this extension is used, producers MUST set the value of the `recordedtime`
|
||||
attribute to the timestamp of when they create the owning CloudEvent.
|
||||
|
||||
If the same occurrence MUST be recorded differently, or the event data or
|
||||
attributes of a previous record of the occurrence MUST be amended or redacted,
|
||||
then the new CloudEvent with the necessary changes SHOULD have a different
|
||||
`recordedtime` attribute value than the previous record of the occurrence.
|
||||
|
||||
Intermediaries MUST NOT change the value of the `recordedtime` attribute.
|
||||
|
||||
## Use cases
|
||||
|
||||
Examples of when an occurrence might need to be recorded differently are:
|
||||
|
||||
- When incompatible changes to the event data schema are made, and there are
|
||||
systems that can only process the new schema.
|
||||
- When a previous record contains incorrect information.
|
||||
- When a previous record contains personal information that can no longer be
|
||||
kept because of regulatory or statutory reasons and needs to be redacted.
|
||||
|
||||
Having bitemporal data makes it easier to get reproducible datasets for
|
||||
analytics and data science, as the datasets can be created by placing
|
||||
constraints on both the `time` and `recordedtime` attributes of events.
|
||||
|
||||
Knowing when an occurrence was recorded in a particular event also makes it
|
||||
possible to determine latency between event producers and consumers. It also
|
||||
makes it possible to do operations which are sensitive to the time when an event
|
||||
was recorded, such as capturing events into time-intervalled files.
|
||||
|
||||
The recorded time also makes it easier to differentiate different records of the
|
||||
same occurrence in analytical data stores.
|
|
@ -1,4 +1,4 @@
|
|||
# Sampling extension
|
||||
# Sampled Rate Extension
|
||||
|
||||
There are many cases in an Event's life when a system (either the system
|
||||
creating the event or a system transporting the event) might wish to only emit a
|
||||
|
@ -17,13 +17,33 @@ emitted event represents a given number of other similar events. It also
|
|||
provides a place for intermediary transport systems to modify the event when
|
||||
they impose additional sampling.
|
||||
|
||||
## Value
|
||||
This specification does not mandate which component (e.g. event source, event
|
||||
producer) is responsible for doing the sampling. Rather just if sampling is
|
||||
done then the attributes defined below are where the metadata would appear
|
||||
within the CloudEvent.
|
||||
|
||||
## Notational Conventions
|
||||
|
||||
As with the main [CloudEvents specification](../spec.md), the key words "MUST",
|
||||
"MUST NOT", "REQUIRED", "SHALL", "SHALL NOT", "SHOULD", "SHOULD NOT",
|
||||
"RECOMMENDED", "MAY", and "OPTIONAL" in this document are to be interpreted as
|
||||
described in [RFC 2119](https://tools.ietf.org/html/rfc2119).
|
||||
|
||||
However, the scope of these key words is limited to when this extension is
|
||||
used. For example, an attribute being marked as "REQUIRED" does not mean
|
||||
it needs to be in all CloudEvents, rather it needs to be included only when
|
||||
this extension is being used.
|
||||
|
||||
## Attributes
|
||||
|
||||
### sampledrate
|
||||
|
||||
- Type: `Integer`
|
||||
- Description: The rate at which this event has already been sampled. Represents
|
||||
the number of similar events that happened but were not sent plus this event.
|
||||
For example, if a system sees 30 occurrences and emits a single event, `rate`
|
||||
would be 30 (29 not sent and 1 sent). A value of `1` is the equivalent of this
|
||||
extension not being used at all.
|
||||
For example, if a system sees 30 occurrences and emits a single event,
|
||||
`sampledrate` would be 30 (29 not sent and 1 sent). A value of `1` is the
|
||||
equivalent of this extension not being used at all.
|
||||
- Constraints
|
||||
- REQUIRED
|
||||
- The rate MUST be greater than zero.
|
|
@ -0,0 +1,46 @@
|
|||
# Sequence
|
||||
|
||||
This extension defines an attribute that can be included within a CloudEvent
|
||||
to describe the position of an event in the ordered sequence of events produced
|
||||
by a unique event source.
|
||||
|
||||
The `sequence` attribute represents the value of this event's order in the
|
||||
stream of events. This specification does not define the meaning or set of
|
||||
valid value of this attribute, rather it only mandates that the value be
|
||||
a string that can be lexicographically compared to other `sequence` values
|
||||
to determine which one comes first. The `sequence` with a lower lexicographical
|
||||
value comes first.
|
||||
|
||||
Produces and consumers are free to define an out-of-band agreement on the
|
||||
semantic meaning, or valid values, for the attribute.
|
||||
|
||||
## Notational Conventions
|
||||
|
||||
As with the main [CloudEvents specification](../spec.md), the key words "MUST",
|
||||
"MUST NOT", "REQUIRED", "SHALL", "SHALL NOT", "SHOULD", "SHOULD NOT",
|
||||
"RECOMMENDED", "MAY", and "OPTIONAL" in this document are to be interpreted as
|
||||
described in [RFC 2119](https://tools.ietf.org/html/rfc2119).
|
||||
|
||||
However, the scope of these key words is limited to when this extension is
|
||||
used. For example, an attribute being marked as "REQUIRED" does not mean
|
||||
it needs to be in all CloudEvents, rather it needs to be included only when
|
||||
this extension is being used.
|
||||
|
||||
## Attributes
|
||||
|
||||
### sequence
|
||||
|
||||
- Type: `String`
|
||||
- Description: Value expressing the relative order of the event. This enables
|
||||
interpretation of data supercedence.
|
||||
- Constraints
|
||||
- REQUIRED
|
||||
- MUST be a non-empty lexicographically-orderable string
|
||||
- RECOMMENDED as monotonically increasing and contiguous
|
||||
|
||||
The entity creating the CloudEvent MUST ensure that the `sequence` values
|
||||
used are formatted such that across the entire set of values used a receiver
|
||||
can determine the order of the events via a simple string-compare type of
|
||||
operation. This means that it might be necessary for the value to include
|
||||
some kind of padding (e.g. leading zeros in the case of the value being the
|
||||
string representation of an integer).
|
|
@ -0,0 +1,80 @@
|
|||
# Severity Extension
|
||||
|
||||
## Abstract
|
||||
This extension defines attributes that MAY be included within a CloudEvent
|
||||
to describe the "severity" or "level" of an event in relation to other events.
|
||||
|
||||
Often systems produce events in form of logs, and these types of events usually
|
||||
share a common concept of "log-level". This extension aims to provide a
|
||||
standard way for describing this property in a language agnostic form.
|
||||
|
||||
Sharing a common way to describe severity of events allows for better
|
||||
monitoring systems, tooling and general log consumption.
|
||||
|
||||
This extension is heavily inspired by the
|
||||
[OpenTelemetry Severity Fields](https://github.com/open-telemetry/opentelemetry-specification/blob/main/specification/logs/data-model.md#severity-fields)
|
||||
and is intended to interoperate with them.
|
||||
|
||||
## Notational Conventions
|
||||
|
||||
As with the main [CloudEvents specification](../spec.md), the key words "MUST",
|
||||
"MUST NOT", "REQUIRED", "SHALL", "SHALL NOT", "SHOULD", "SHOULD NOT",
|
||||
"RECOMMENDED", "MAY", and "OPTIONAL" in this document are to be interpreted as
|
||||
described in [RFC 2119](https://tools.ietf.org/html/rfc2119).
|
||||
|
||||
However, the scope of these key words is limited to when this extension is
|
||||
used. For example, an attribute being marked as "REQUIRED" does not mean
|
||||
it needs to be in all CloudEvents, rather it needs to be included only when
|
||||
this extension is being used.
|
||||
|
||||
## Attributes
|
||||
|
||||
When both attributes are used, all `severitytext` values which MAY be produced
|
||||
in a context of a `source` SHOULD be in a
|
||||
[one-to-one and onto](https://en.wikipedia.org/wiki/Bijection) relationship
|
||||
with all `severitynumber` values which MAY be produced by the same `source`.
|
||||
|
||||
|
||||
### severitytext
|
||||
|
||||
- Type: `String`
|
||||
- Description: Human readable text representation of the event severity (also
|
||||
known as log level name).
|
||||
|
||||
This is the original string representation of the severity as it is known
|
||||
at the source. If this field is missing and `severitynumber` is present then
|
||||
the [short name](https://github.com/open-telemetry/opentelemetry-specification/blob/main/specification/logs/data-model.md#displaying-severity)
|
||||
that corresponds to the `severitynumber` MAY be used as a substitution.
|
||||
|
||||
- Constraints
|
||||
- OPTIONAL
|
||||
- if present, MUST be a non-empty string
|
||||
- SHOULD be uppercase
|
||||
- RECOMMENDED values are `TRACE`, `DEBUG`, `INFO`, `WARN`, `ERROR`, and
|
||||
`FATAL`, but others MAY be used.
|
||||
|
||||
### severitynumber
|
||||
|
||||
- Type: `Integer`
|
||||
- Description: Numerical representation of the event severity (also known as
|
||||
log level number), normalized to values described in this document.
|
||||
|
||||
Severity of all values MUST be numerically ascending from least-severe
|
||||
to most-severe. An event with a lower numerical value (such as a debug event)
|
||||
MUST be less severe than an event with a higher numerical value (such as
|
||||
an error event).
|
||||
|
||||
See OpenTelemetry for [exact severity number meanings](https://github.com/open-telemetry/opentelemetry-specification/blob/main/specification/logs/data-model.md#field-severitynumber)
|
||||
|
||||
- Constraints
|
||||
- REQUIRED
|
||||
- if present, MUST NOT be negative
|
||||
|
||||
|
||||
# References
|
||||
- [Mapping of SeverityNumber](https://github.com/open-telemetry/opentelemetry-specification/blob/main/specification/logs/data-model.md#mapping-of-severitynumber)
|
||||
- [Reverse Mapping](https://github.com/open-telemetry/opentelemetry-specification/blob/main/specification/logs/data-model.md#reverse-mapping)
|
||||
- [Error Semantics](https://github.com/open-telemetry/opentelemetry-specification/blob/main/specification/logs/data-model.md#error-semantics)
|
||||
- [Displaying Severity](https://github.com/open-telemetry/opentelemetry-specification/blob/main/specification/logs/data-model.md#displaying-severity)
|
||||
- [Comparing Severity](https://github.com/open-telemetry/opentelemetry-specification/blob/main/specification/logs/data-model.md#comparing-severity)
|
||||
- [Mapping of existing log formats to severity levels](https://github.com/open-telemetry/opentelemetry-specification/blob/main/specification/logs/data-model.md#appendix-a-example-mappings)
|
|
@ -1,27 +1,23 @@
|
|||
# Avro Event Format for CloudEvents - Version 1.0.1
|
||||
# Avro Event Format for CloudEvents - Version 1.0.3-wip
|
||||
|
||||
## Abstract
|
||||
|
||||
The Avro Format for CloudEvents defines how events attributes are expressed in
|
||||
The Avro Format for CloudEvents defines how events are expressed in
|
||||
the [Avro 1.9.0 Specification][avro-spec].
|
||||
|
||||
## Status of this document
|
||||
|
||||
This document is a working draft.
|
||||
|
||||
## Table of Contents
|
||||
|
||||
1. [Introduction](#1-introduction)
|
||||
2. [Attributes](#2-attributes)
|
||||
3. [Data](#3-data)
|
||||
4. [Examples](#4-examples)
|
||||
4. [Transport](#4-transport)
|
||||
4. [Examples](#5-examples)
|
||||
|
||||
## 1. Introduction
|
||||
|
||||
[CloudEvents][ce] is a standardized and protocol-agnostic definition of the
|
||||
structure and metadata description of events. This specification defines how the
|
||||
elements defined in the CloudEvents specification are to be represented in the
|
||||
[Avro 1.9.0][avro-primitives].
|
||||
CloudEvents are to be represented as [Avro 1.9.0][avro-primitives].
|
||||
|
||||
The [Attributes](#2-attributes) section describes the naming conventions and
|
||||
data type mappings for CloudEvents attributes for use as Avro message
|
||||
|
@ -31,6 +27,8 @@ This specification does not define an envelope format. The Avro type system's
|
|||
intent is primarily to provide a consistent type system for Avro itself and not
|
||||
for message payloads.
|
||||
|
||||
The Avro event format does not currently define a batch mode format.
|
||||
|
||||
### 1.1. Conformance
|
||||
|
||||
The key words "MUST", "MUST NOT", "REQUIRED", "SHALL", "SHALL NOT", "SHOULD",
|
||||
|
@ -47,7 +45,7 @@ type-system. This specification explicitly maps each attribute.
|
|||
The CloudEvents type system MUST be mapped to Avro types as follows.
|
||||
|
||||
| CloudEvents | Avro |
|
||||
| ------------- | ---------------------------------------------------------------------- |
|
||||
|---------------|------------------------------------------------------------------------|
|
||||
| Boolean | [boolean][avro-primitives] |
|
||||
| Integer | [int][avro-primitives] |
|
||||
| String | [string][avro-primitives] |
|
||||
|
@ -75,7 +73,7 @@ Example:
|
|||
### 2.4 Definition
|
||||
|
||||
Users of Avro MUST use a message whose binary encoding is identical to the one
|
||||
described by the [CloudEvent Avro Schema](./spec.avsc):
|
||||
described by the [CloudEvent Avro Schema](cloudevents.avsc):
|
||||
|
||||
```json
|
||||
{
|
||||
|
@ -150,24 +148,29 @@ For other types (non-binary data without a `datacontenttype` attribute), the
|
|||
implementation MUST translate the data value into a representation of the JSON
|
||||
value using the union types described for the `data` record.
|
||||
|
||||
## 4 Examples
|
||||
## 4 Transport
|
||||
|
||||
Transports that support content identification MUST use the following designation:
|
||||
|
||||
```text
|
||||
application/cloudevents+avro
|
||||
```
|
||||
|
||||
## 5 Examples
|
||||
|
||||
The following table shows exemplary mappings:
|
||||
|
||||
| CloudEvents | Type | Exemplary Avro Value |
|
||||
| ----------- | ------ | ---------------------------------------------- |
|
||||
| type | string | `"com.example.someevent"` |
|
||||
| specversion | string | `"1.0"` |
|
||||
| source | string | `"/mycontext"` |
|
||||
| id | string | `"7a0dc520-c870-4193c8"` |
|
||||
| time | string | `"2019-06-05T23:45:00Z"` |
|
||||
| dataschema | string | `"http://registry.com/schema/v1/much.json"` |
|
||||
| contenttype | string | `"application/json"` |
|
||||
| data | bytes | `"{"much":{"wow":"json"}}"` |
|
||||
| | | |
|
||||
| dataschema | string | `"http://registry.com/subjects/ce/versions/1"` |
|
||||
| contenttype | string | `"application/avro"` |
|
||||
| data | bytes | `[avro-serialized-bytes]` |
|
||||
| CloudEvents | Type | Exemplary Avro Value |
|
||||
|-----------------|--------|-------------------------------------------|
|
||||
| id | string | `7a0dc520-c870-4193c8` |
|
||||
| source | string | `https://github.com/cloudevents` |
|
||||
| specversion | string | `1.0` |
|
||||
| type | string | `com.example.object.deleted.v2` |
|
||||
| datacontenttype | string | `application/octet-stream` |
|
||||
| dataschema | string | `http://registry.com/schema/v1/much.json` |
|
||||
| subject | string | `mynewfile.jpg` |
|
||||
| time | string | `2019-06-05T23:45:00Z` |
|
||||
| data | bytes | `[bytes]` |
|
||||
|
||||
## References
|
||||
|
||||
|
@ -177,7 +180,7 @@ The following table shows exemplary mappings:
|
|||
[avro-primitives]: http://avro.apache.org/docs/1.9.0/spec.html#schema_primitive
|
||||
[avro-logical-types]: http://avro.apache.org/docs/1.9.0/spec.html#Logical+Types
|
||||
[avro-unions]: http://avro.apache.org/docs/1.9.0/spec.html#Unions
|
||||
[ce]: ./spec.md
|
||||
[ce]: ../spec.md
|
||||
[rfc2119]: https://tools.ietf.org/html/rfc2119
|
||||
[rfc3986-section41]: https://tools.ietf.org/html/rfc3986#section-4.1
|
||||
[rfc3986-section43]: https://tools.ietf.org/html/rfc3986#section-4.3
|
|
@ -1,7 +1,7 @@
|
|||
/**
|
||||
* CloudEvent Protobuf Format
|
||||
*
|
||||
* - Required context attributes are explicity represented.
|
||||
* - Required context attributes are explicitly represented.
|
||||
* - Optional and Extension context attributes are carried in a map structure.
|
||||
* - Data may be represented as binary, text, or protobuf messages.
|
||||
*/
|
||||
|
@ -13,6 +13,7 @@ package io.cloudevents.v1;
|
|||
import "google/protobuf/any.proto";
|
||||
import "google/protobuf/timestamp.proto";
|
||||
|
||||
option csharp_namespace = "CloudNative.CloudEvents.V1";
|
||||
option go_package = "cloudevents.io/genproto/v1";
|
||||
option java_package = "io.cloudevents.v1.proto";
|
||||
option java_multiple_files = true;
|
||||
|
@ -56,4 +57,13 @@ message CloudEvent {
|
|||
google.protobuf.Timestamp ce_timestamp = 7;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* CloudEvent Protobuf Batch Format
|
||||
*
|
||||
*/
|
||||
|
||||
message CloudEventBatch {
|
||||
repeated CloudEvent events = 1;
|
||||
}
|
|
@ -1,14 +1,10 @@
|
|||
# JSON Event Format for CloudEvents - Version 1.0.1
|
||||
# JSON Event Format for CloudEvents - Version 1.0.3-wip
|
||||
|
||||
## Abstract
|
||||
|
||||
The JSON Format for CloudEvents defines how events are expressed in JavaScript
|
||||
Object Notation (JSON) Data Interchange Format ([RFC8259][rfc8259]).
|
||||
|
||||
## Status of this document
|
||||
|
||||
This document is a working draft.
|
||||
|
||||
## Table of Contents
|
||||
|
||||
1. [Introduction](#1-introduction)
|
||||
|
@ -44,11 +40,11 @@ mapping model that applies to all current and future CloudEvents attributes,
|
|||
including extensions.
|
||||
|
||||
For clarity, extension attributes are serialized using the same rules as
|
||||
specification defined attributes. This includes their syntax and placement
|
||||
core attributes. This includes their syntax and placement
|
||||
within the JSON object. In particular, extensions are placed as top-level JSON
|
||||
properties. Extensions MUST be serialized as a top-level JSON property. There
|
||||
were many reasons for this design decision and they are covered in more detail
|
||||
in the [Primer](primer.md#json-extensions).
|
||||
in the [Primer](../primer.md#json-extensions).
|
||||
|
||||
### 2.1. Base Type System
|
||||
|
||||
|
@ -63,7 +59,7 @@ with exceptions noted below.
|
|||
| CloudEvents | JSON |
|
||||
| ------------- | -------------------------------------------------------------- |
|
||||
| Boolean | [boolean][json-bool] |
|
||||
| Integer | [number][json-number], only the `int` component is permitted |
|
||||
| Integer | [number][json-number], only the integer component optionally prefixed with a minus sign is permitted |
|
||||
| String | [string][json-string] |
|
||||
| Binary | [string][json-string], [Base64-encoded][base64] binary |
|
||||
| URI | [string][json-string] following [RFC 3986][rfc3986] |
|
||||
|
@ -88,10 +84,10 @@ any revision of such a specification, MUST also define explicit mapping rules
|
|||
for all other event formats that are part of the CloudEvents core at the time of
|
||||
the submission or revision.
|
||||
|
||||
If required, like when decoding Maps, the CloudEvents type can be determined by
|
||||
inference using the rules from the mapping table, whereby the only potentially
|
||||
ambiguous JSON data type is `string`. The value is compatible with the
|
||||
respective CloudEvents type when the mapping rules are fulfilled.
|
||||
If necessary, the CloudEvents type can be determined by inference using the rules
|
||||
from the mapping table, whereby the only potentially ambiguous JSON data type is
|
||||
`string`. The value is compatible with the respective CloudEvents type when the
|
||||
mapping rules are fulfilled.
|
||||
|
||||
### 2.3. Examples
|
||||
|
||||
|
@ -112,7 +108,8 @@ The following table shows exemplary attribute mappings:
|
|||
### 2.4. JSONSchema Validation
|
||||
|
||||
The CloudEvents [JSONSchema](http://json-schema.org) for the spec is located
|
||||
[here](spec.json) and contains the definitions for validating events in JSON.
|
||||
[here](cloudevents.json) and contains the definitions for validating events in
|
||||
JSON.
|
||||
|
||||
## 3. Envelope
|
||||
|
||||
|
@ -125,38 +122,100 @@ become members of the JSON object, with the respective JSON object member name
|
|||
matching the attribute name, and the member's type and value being mapped using
|
||||
the [type system mapping](#22-type-system-mapping).
|
||||
|
||||
OPTIONAL not omitted attributes MAY be represeted as a `null` JSON value.
|
||||
OPTIONAL not omitted attributes MAY be represented as a `null` JSON value.
|
||||
|
||||
### 3.1. Handling of "data"
|
||||
|
||||
The JSON representation of the event "data" payload is determined by the runtime
|
||||
type of the `data` content and the value of the [`datacontenttype`
|
||||
attribute][datacontenttype].
|
||||
|
||||
#### 3.1.1. Payload Serialization
|
||||
|
||||
Before taking action, a JSON serializer MUST first determine the runtime data
|
||||
type of the `data` content.
|
||||
|
||||
If the implementation determines that the type of data is `Binary`, the value
|
||||
MUST be represented as a [JSON string][json-string] expression containing the
|
||||
[Base64][base64] encoded binary value, and use the member name `data_base64` to
|
||||
store it inside the JSON object.
|
||||
store it inside the JSON representation. If present, the `datacontenttype` MUST
|
||||
reflect the format of the original binary data. If a `datacontenttype` value is
|
||||
not provided, no assumptions can be made as to the format of the data and
|
||||
therefore the `datacontenttype` attribute MUST NOT be present in the resulting
|
||||
CloudEvent.
|
||||
|
||||
For any other type, the implementation MUST translate the data value into a
|
||||
[JSON value][json-value], and use the member name `data` to store it inside the
|
||||
JSON object.
|
||||
Note: Definition of `data_base64` is a JSON-specific marshaling rule and not
|
||||
part of the formal CloudEvents context attributes definition. This means the
|
||||
rules governing CloudEvent attributes names do not apply to this JSON member.
|
||||
|
||||
Out of this follows that use of the `data` and `data_base64` members is mutually
|
||||
exclusive in a JSON serialized CloudEvent.
|
||||
If the type of data is not `Binary`, the implementation will next determine
|
||||
whether the value of the `datacontenttype` attribute declares the `data` to
|
||||
contain JSON-formatted content. Such a content type is defined as one having a
|
||||
[media subtype][rfc2045-sec5] equal to `json` or ending with a `+json` format
|
||||
extension. That is, a `datacontenttype` declares JSON-formatted content if its
|
||||
media type, when stripped of parameters, has the form `*/json` or `*/*+json`.
|
||||
If the `datacontenttype` is unspecified, processing SHOULD proceed as if the
|
||||
`datacontenttype` had been specified explicitly as `application/json`.
|
||||
|
||||
If the `datacontenttype` declares the data to contain JSON-formatted content, a
|
||||
JSON serializer MUST translate the data value to a [JSON value][json-value], and
|
||||
use the member name `data` to store it inside the JSON representation. The data
|
||||
value MUST be stored directly as a JSON value, rather than as an encoded JSON
|
||||
document represented as a string. An implementation MAY fail to serialize the
|
||||
event if it is unable to translate the runtime value to a JSON value.
|
||||
|
||||
Otherwise, if the `datacontenttype` does not declare JSON-formatted data
|
||||
content, a JSON serializer MUST store a string representation of the data value,
|
||||
properly encoded according to the `datacontenttype`, in the `data` member of the
|
||||
JSON representation. An implementation MAY fail to serialize the event if it is
|
||||
unable to represent the runtime value as a properly encoded string.
|
||||
|
||||
Out of this follows that the presence of the `data` and `data_base64` members is
|
||||
mutually exclusive in a JSON serialized CloudEvent.
|
||||
|
||||
Furthermore, unlike attributes, for which value types are restricted by the
|
||||
[type-system mapping](#22-type-system-mapping), the `data` member
|
||||
[JSON value][json-value] is unrestricted, and MAY contain any valid JSON if the
|
||||
`datacontenttype` declares the data to be JSON-formatted. In particular, the
|
||||
`data` member MAY have a value of `null`, representing an explicit `null`
|
||||
payload as distinct from the absence of the `data` member.
|
||||
|
||||
#### 3.1.2. Payload Deserialization
|
||||
|
||||
When a CloudEvents is deserialized from JSON, the presence of the `data_base64`
|
||||
member clearly indicates that the value is a Base64 encoded binary data, which
|
||||
the serializer MUST decode into a binary runtime data type. When a `data` member
|
||||
is present, it is decoded using the default JSON type mapping for the used
|
||||
runtime.
|
||||
the deserializer MUST decode into a binary runtime data type. The deserializer
|
||||
MAY further interpret this binary data according to the `datacontenttype`. If
|
||||
the `datacontenttype` attribute is absent, the decoding MUST NOT make an
|
||||
assumption of JSON-formatted data (as described below for the `data` member).
|
||||
|
||||
Unlike attributes, for which value types are restricted to strings per the
|
||||
[type-system mapping](#22-type-system-mapping), the resulting `data` member
|
||||
[JSON value][json-value] is unrestricted, and MAY contain any valid JSON.
|
||||
When a `data` member is present, the decoding behavior is dependent on the value
|
||||
of the `datacontenttype` attribute. If the `datacontenttype` declares the `data`
|
||||
to contain JSON-formatted content (that is, its subtype is `json` or has a
|
||||
`+json` format extension), then the `data` member MUST be treated directly as a
|
||||
[JSON value][json-value] and decoded using an appropriate JSON type mapping for
|
||||
the runtime. Note: if the `data` member is a string, a JSON deserializer MUST
|
||||
interpret it directly as a [JSON String][json-string] value; it MUST NOT further
|
||||
deserialize the string as a JSON document.
|
||||
|
||||
If the `datacontenttype` does not declare JSON-formatted data content, then the
|
||||
`data` member SHOULD be treated as an encoded content string. An implementation
|
||||
MAY fail to deserialize the event if the `data` member is not a string, or if it
|
||||
is unable to interpret the `data` with the `datacontenttype`.
|
||||
|
||||
When a `data` member is present, if the `datacontenttype` attribute is absent, a
|
||||
JSON deserializer SHOULD proceed as if it were set to `application/json`, which
|
||||
declares the data to contain JSON-formatted content. Thus, it SHOULD treat the
|
||||
`data` member directly as a [JSON value][json-value] as specified above.
|
||||
Furthermore, if a JSON-formatted event with no `datacontenttype` attribute, is
|
||||
deserialized and then re-serialized using a different format or protocol
|
||||
binding, the `datacontenttype` in the re-serialized event SHOULD be set
|
||||
explicitly to the implied `application/json` content type to preserve the
|
||||
semantics of the event.
|
||||
|
||||
### 3.2. Examples
|
||||
|
||||
Example event with `String`-valued `data`:
|
||||
Example event with `Binary`-valued data:
|
||||
|
||||
```JSON
|
||||
{
|
||||
|
@ -167,13 +226,28 @@ Example event with `String`-valued `data`:
|
|||
"time" : "2018-04-05T17:31:00Z",
|
||||
"comexampleextension1" : "value",
|
||||
"comexampleothervalue" : 5,
|
||||
"unsetextension": null,
|
||||
"datacontenttype" : "text/xml",
|
||||
"data" : "<much wow=\"xml\"/>"
|
||||
"datacontenttype" : "application/vnd.apache.thrift.binary",
|
||||
"data_base64" : "... base64 encoded string ..."
|
||||
}
|
||||
```
|
||||
|
||||
Example event with `Binary`-valued data
|
||||
The above example re-encoded using [HTTP Binary Content Mode][http-binary]:
|
||||
|
||||
```
|
||||
ce-specversion: 1.0
|
||||
ce-type: com.example.someevent
|
||||
ce-source: /mycontext
|
||||
ce-id: A234-1234-1234
|
||||
ce-time: 2018-04-05T17:31:00Z
|
||||
ce-comexampleextension1: value
|
||||
ce-comexampleothervalue: 5
|
||||
content-type: application/vnd.apache.thrift.binary
|
||||
|
||||
...raw binary bytes...
|
||||
```
|
||||
|
||||
Example event with a serialized XML document as the `String` (i.e. non-`Binary`)
|
||||
valued `data`, and an XML (i.e. non-JSON-formatted) content type:
|
||||
|
||||
```JSON
|
||||
{
|
||||
|
@ -184,13 +258,29 @@ Example event with `Binary`-valued data
|
|||
"time" : "2018-04-05T17:31:00Z",
|
||||
"comexampleextension1" : "value",
|
||||
"comexampleothervalue" : 5,
|
||||
"datacontenttype" : "application/vnd.apache.thrift.binary",
|
||||
"data_base64" : "... base64 encoded string ..."
|
||||
"unsetextension": null,
|
||||
"datacontenttype" : "application/xml",
|
||||
"data" : "<much wow=\"xml\"/>"
|
||||
}
|
||||
```
|
||||
|
||||
Example event with JSON data for the "data" member, either derived from a `Map`
|
||||
or [JSON data](#31-handling-of-data) data:
|
||||
The above example re-encoded using [HTTP Binary Content Mode][http-binary]:
|
||||
|
||||
```
|
||||
ce-specversion: 1.0
|
||||
ce-type: com.example.someevent
|
||||
ce-source: /mycontext
|
||||
ce-id: B234-1234-1234
|
||||
ce-time: 2018-04-05T17:31:00Z
|
||||
ce-comexampleextension1: value
|
||||
ce-comexampleothervalue: 5
|
||||
content-type: application/xml
|
||||
|
||||
<much wow="xml"/>
|
||||
```
|
||||
|
||||
Example event with [JSON Object][json-object]-valued `data` and a content type
|
||||
declaring JSON-formatted data:
|
||||
|
||||
```JSON
|
||||
{
|
||||
|
@ -211,17 +301,128 @@ or [JSON data](#31-handling-of-data) data:
|
|||
}
|
||||
```
|
||||
|
||||
The above example re-encoded using [HTTP Binary Content Mode][http-binary]:
|
||||
|
||||
```
|
||||
ce-specversion: 1.0
|
||||
ce-type: com.example.someevent
|
||||
ce-source: /mycontext
|
||||
ce-id: C234-1234-1234
|
||||
ce-time: 2018-04-05T17:31:00Z
|
||||
ce-comexampleextension1: value
|
||||
ce-comexampleothervalue: 5
|
||||
content-type: application/json
|
||||
|
||||
{
|
||||
"appinfoA" : "abc",
|
||||
"appinfoB" : 123,
|
||||
"appinfoC" : true
|
||||
}
|
||||
```
|
||||
|
||||
Example event with [JSON Number][json-number]-valued `data` and a content type
|
||||
declaring JSON-formatted data:
|
||||
|
||||
```JSON
|
||||
{
|
||||
"specversion" : "1.0",
|
||||
"type" : "com.example.someevent",
|
||||
"source" : "/mycontext",
|
||||
"subject": null,
|
||||
"id" : "C234-1234-1234",
|
||||
"time" : "2018-04-05T17:31:00Z",
|
||||
"comexampleextension1" : "value",
|
||||
"comexampleothervalue" : 5,
|
||||
"datacontenttype" : "application/json",
|
||||
"data" : 1.5
|
||||
}
|
||||
```
|
||||
|
||||
The above example re-encoded using [HTTP Binary Content Mode][http-binary]:
|
||||
|
||||
```
|
||||
ce-specversion: 1.0
|
||||
ce-type: com.example.someevent
|
||||
ce-source: /mycontext
|
||||
ce-id: C234-1234-1234
|
||||
ce-time: 2018-04-05T17:31:00Z
|
||||
ce-comexampleextension1: value
|
||||
ce-comexampleothervalue: 5
|
||||
content-type: application/json
|
||||
|
||||
1.5
|
||||
```
|
||||
|
||||
Example event with a literal JSON string as the non-`Binary`-valued `data` and
|
||||
no `datacontenttype`. The data is implicitly treated as if the `datacontenttype`
|
||||
were set to `application/json`:
|
||||
|
||||
```JSON
|
||||
{
|
||||
"specversion" : "1.0",
|
||||
"type" : "com.example.someevent",
|
||||
"source" : "/mycontext",
|
||||
"subject": null,
|
||||
"id" : "D234-1234-1234",
|
||||
"time" : "2018-04-05T17:31:00Z",
|
||||
"comexampleextension1" : "value",
|
||||
"comexampleothervalue" : 5,
|
||||
"data" : "I'm just a string"
|
||||
}
|
||||
```
|
||||
|
||||
The above example re-encoded using [HTTP Binary Content Mode][http-binary].
|
||||
Note that the Content Type is explicitly set to the `application/json` value
|
||||
that was implicit in JSON format. Note also that the content is quoted to
|
||||
indicate that it is a literal JSON string. If the quotes were missing, this
|
||||
would have been an invalid event because the content could not be decoded as
|
||||
`application/json`:
|
||||
|
||||
```
|
||||
ce-specversion: 1.0
|
||||
ce-type: com.example.someevent
|
||||
ce-source: /mycontext
|
||||
ce-id: D234-1234-1234
|
||||
ce-time: 2018-04-05T17:31:00Z
|
||||
ce-comexampleextension1: value
|
||||
ce-comexampleothervalue: 5
|
||||
content-type: application/json
|
||||
|
||||
"I'm just a string"
|
||||
```
|
||||
|
||||
Example event with a `Binary`-valued `data_base64` but no `datacontenttype`.
|
||||
Even though the data happens to be a valid JSON document when interpreted as
|
||||
text, no content type is inferred.
|
||||
|
||||
```JSON
|
||||
{
|
||||
"specversion" : "1.0",
|
||||
"type" : "com.example.someevent",
|
||||
"source" : "/mycontext",
|
||||
"id" : "D234-1234-1234",
|
||||
"data_base64" : "eyAieHl6IjogMTIzIH0="
|
||||
}
|
||||
```
|
||||
|
||||
The above example re-encoded using [HTTP Binary Content Mode][http-binary].
|
||||
Note that there is no `content-type` header present.
|
||||
|
||||
```
|
||||
ce-specversion: 1.0
|
||||
ce-type: com.example.someevent
|
||||
ce-source: /mycontext
|
||||
ce-id: D234-1234-1234
|
||||
|
||||
{ "xyz": 123 }
|
||||
```
|
||||
|
||||
## 4. JSON Batch Format
|
||||
|
||||
In the _JSON Batch Format_ several CloudEvents are batched into a single JSON
|
||||
document. The document is a JSON array filled with CloudEvents in the [JSON
|
||||
Event format][json-format].
|
||||
|
||||
Although the _JSON Batch Format_ builds ontop of the _JSON Format_, it is
|
||||
considered as a separate format: a valid implementation of the _JSON Format_
|
||||
doesn't need to support it. The _JSON Batch Format_ MUST NOT be used when only
|
||||
support for the _JSON Format_ is indicated.
|
||||
|
||||
### 4.1. Mapping CloudEvents
|
||||
|
||||
This section defines how a batch of CloudEvents is mapped to JSON.
|
||||
|
@ -291,10 +492,12 @@ also valid in a request):
|
|||
Format
|
||||
|
||||
[base64]: https://tools.ietf.org/html/rfc4648#section-4
|
||||
[ce]: ./spec.md
|
||||
[ce-types]: ./spec.md#type-system
|
||||
[ce]: ../spec.md
|
||||
[ce-types]: ../spec.md#type-system
|
||||
[content-type]: https://tools.ietf.org/html/rfc7231#section-3.1.1.5
|
||||
[json-format]: ./json-format.md
|
||||
[datacontenttype]: ../spec.md#datacontenttype
|
||||
[http-binary]: ../bindings/http-protocol-binding.md#31-binary-content-mode
|
||||
[json-format]: ../formats/json-format.md
|
||||
[json-geoseq]:https://www.iana.org/assignments/media-types/application/geo+json-seq
|
||||
[json-object]: https://tools.ietf.org/html/rfc7159#section-4
|
||||
[json-seq]: https://www.iana.org/assignments/media-types/application/json-seq
|
||||
|
@ -303,6 +506,7 @@ also valid in a request):
|
|||
[json-string]: https://tools.ietf.org/html/rfc7159#section-7
|
||||
[json-value]: https://tools.ietf.org/html/rfc7159#section-3
|
||||
[json-array]: https://tools.ietf.org/html/rfc7159#section-5
|
||||
[rfc2045-sec5]: https://tools.ietf.org/html/rfc2045#section-5
|
||||
[rfc2046]: https://tools.ietf.org/html/rfc2046
|
||||
[rfc2119]: https://tools.ietf.org/html/rfc2119
|
||||
[rfc3986]: https://tools.ietf.org/html/rfc3986
|
|
@ -1,4 +1,4 @@
|
|||
# Protobuf Event Format for CloudEvents - Version 1.0-rc1
|
||||
# Protobuf Event Format for CloudEvents - Version 1.0.3-wip
|
||||
|
||||
## Abstract
|
||||
|
||||
|
@ -9,23 +9,20 @@ of that specification.
|
|||
In this document the terms *Protocol Buffers*, *protobuf*, and *proto* are used
|
||||
interchangeably.
|
||||
|
||||
## Status of this document
|
||||
|
||||
This document is a working draft.
|
||||
|
||||
## Table of Contents
|
||||
|
||||
1. [Introduction](#1-introduction)
|
||||
2. [Attributes](#2-attributes)
|
||||
3. [Data](#3-data)
|
||||
4. [Transport](#4-transport)
|
||||
5. [Examples](#5-examples)
|
||||
5. [Batch Format](#5-batch-format)
|
||||
6. [Examples](#6-examples)
|
||||
|
||||
## 1. Introduction
|
||||
|
||||
[CloudEvents][ce] is a standardized and protocol-agnostic definition of the
|
||||
structure and metadata description of events. This specification defines how the
|
||||
elements defined in the CloudEvents specification are are represented using
|
||||
elements defined in the CloudEvents specification are represented using
|
||||
a protobuf schema.
|
||||
|
||||
The [Attributes](#2-attributes) section describes the naming conventions and
|
||||
|
@ -128,8 +125,6 @@ oneof data {
|
|||
* When the type of the data is binary the value MUST be stored in the `binary_data` property.
|
||||
* `datacontenttype` SHOULD be populated with the appropriate media-type.
|
||||
|
||||
|
||||
|
||||
## 4. Transport
|
||||
|
||||
Transports that support content identification MUST use the following designation:
|
||||
|
@ -138,12 +133,37 @@ Transports that support content identification MUST use the following designatio
|
|||
application/cloudevents+protobuf
|
||||
```
|
||||
|
||||
## 5. Examples
|
||||
## 5. Batch Format
|
||||
|
||||
The following code-snippets show how proto representations might be constucted
|
||||
In the _Protobuf Batch Format_ several CloudEvents are batched into a single Protobuf
|
||||
message. The message contains a repeated field filled with independent CloudEvent messages
|
||||
in the structured mode Protobuf event format.
|
||||
|
||||
### 5.1 Envelope
|
||||
|
||||
The enveloping container is a _CloudEventBatch_ protobuf message containing a
|
||||
repeating set of _CloudEvent_ message(s):
|
||||
|
||||
```proto
|
||||
message CloudEventBatch {
|
||||
repeated CloudEvent events = 1;
|
||||
}
|
||||
```
|
||||
|
||||
### 5.2 Batch Media Type
|
||||
|
||||
A compliant protobuf batch representation is identifed using the following media-type
|
||||
|
||||
```text
|
||||
application/cloudevents-batch+protobuf
|
||||
```
|
||||
|
||||
## 6. Examples
|
||||
|
||||
The following code-snippets show how proto representations might be constructed
|
||||
assuming the availability of some convenience methods.
|
||||
|
||||
### 5.1 Plain Text event data
|
||||
### 6.1 Plain Text event data
|
||||
|
||||
```java
|
||||
public static CloudEvent plainTextExample() {
|
||||
|
@ -169,7 +189,7 @@ public static CloudEvent plainTextExample() {
|
|||
|
||||
```
|
||||
|
||||
### 5.2 Proto message as event data
|
||||
### 6.2 Proto message as event data
|
||||
|
||||
Where the event data payload is itself a protobuf message (with its own schema)
|
||||
a protocol buffer idiomatic method can be used to carry the data.
|
||||
|
@ -213,15 +233,14 @@ private static Spec.CloudEvent protoExample() {
|
|||
* [Protocol Buffer 3 Specification][proto-3]
|
||||
* [CloudEvents Protocol Buffers format schema][proto-schema]
|
||||
|
||||
[Proto-3]: https://developers.google.com/protocol-buffers/docs/reference/proto3-spec
|
||||
[proto-3]: https://developers.google.com/protocol-buffers/docs/reference/proto3-spec
|
||||
[proto-home]: https://developers.google.com/protocol-buffers
|
||||
[proto-scalars]: https://developers.google.com/protocol-buffers/docs/proto3#scalar
|
||||
[proto-wellknown]: https://developers.google.com/protocol-buffers/docs/reference/google.protobuf
|
||||
[proto-timestamp]: https://developers.google.com/protocol-buffers/docs/reference/google.protobuf#google.protobuf.Timestamp
|
||||
[proto-schema]: ./spec.proto
|
||||
[json-format]: ./json-format.md
|
||||
[ce]: ./spec.md
|
||||
[ce-types]: ./spec.md#type-system
|
||||
[proto-schema]: ./cloudevents.proto
|
||||
[ce]: ../spec.md
|
||||
[ce-types]: ../spec.md#type-system
|
||||
[rfc2119]: https://tools.ietf.org/html/rfc2119
|
||||
[rfc3986-section41]: https://tools.ietf.org/html/rfc3986#section-4.1
|
||||
[rfc3986-section43]: https://tools.ietf.org/html/rfc3986#section-4.3
|
|
@ -1,4 +1,4 @@
|
|||
# HTTP 1.1 Web Hooks for Event Delivery - Version 1.0.1
|
||||
# HTTP 1.1 Web Hooks for Event Delivery - Version 1.0.3-wip
|
||||
|
||||
## Abstract
|
||||
|
||||
|
@ -8,10 +8,6 @@ formal definition for Web Hooks. This specification aims to provide such a
|
|||
definition for use with [CNCF CloudEvents][ce], but is considered generally
|
||||
usable beyond the scope of CloudEvents.
|
||||
|
||||
## Status of this document
|
||||
|
||||
This document is a working draft.
|
||||
|
||||
## Table of Contents
|
||||
|
||||
1. [Introduction](#1-introduction)
|
||||
|
@ -70,10 +66,10 @@ This specification does not further constrain the content of the notification,
|
|||
and it also does not prescribe the [HTTP target resource][rfc7230-section-5-1]
|
||||
that is used for delivery.
|
||||
|
||||
If the delivery target supports and requires
|
||||
[Abuse Protection](#4-abuse-protection), the delivery request MUST include the
|
||||
`Origin` header. The `Origin` header value is a DNS name expression that
|
||||
identifies the sending system.
|
||||
If the delivery target supports and requires [Abuse
|
||||
Protection](#4-abuse-protection), the delivery request MUST include the
|
||||
`WebHook-Request-Origin` header. The `WebHook-Request-Origin` header value is a
|
||||
DNS name expression that identifies the sending system.
|
||||
|
||||
### 2.2. Delivery response
|
||||
|
||||
|
@ -190,7 +186,7 @@ Reaching the delivery agreement is realized using the following validation
|
|||
handshake. The handshake can either be executed immediately at registration time
|
||||
or as a "pre-flight" request immediately preceding a delivery.
|
||||
|
||||
It is important to understand is that the handshake does not aim to establish an
|
||||
It is important to understand that the handshake does not aim to establish an
|
||||
authentication or authorization context. It only serves to protect the sender
|
||||
from being told to a push to a destination that is not expecting the traffic.
|
||||
While this specification mandates use of an authorization model, this mandate is
|
||||
|
@ -225,7 +221,7 @@ instances that act on the behalf of a certain system, and not an individual
|
|||
host.
|
||||
|
||||
After the handshake and if permission has been granted, the sender MUST use the
|
||||
`Origin` request header for each delivery request, with the value matching that
|
||||
`WebHook-Request-Origin` request header for each delivery request, with the value matching that
|
||||
of this header.
|
||||
|
||||
Example:
|
||||
|
@ -246,7 +242,8 @@ log, and call it manually and therewith grant access.
|
|||
|
||||
The delivery target grants permission by issuing an HTTPS GET or POST request
|
||||
against the given URL. The HTTP GET request can be performed manually using a
|
||||
browser client.
|
||||
browser client. If the WebHook-Request-Callback header is used, the callback
|
||||
target MUST support both methods.
|
||||
|
||||
The delivery target MAY include the `WebHook-Allowed-Rate` response in the
|
||||
callback.
|
||||
|
@ -310,13 +307,19 @@ WebHook-Allowed-Origin: eventemitter.example.com
|
|||
or
|
||||
|
||||
```text
|
||||
WebHook-Request-Origin: *
|
||||
WebHook-Allowed-Origin: *
|
||||
```
|
||||
|
||||
#### 4.2.2. WebHook-Allowed-Rate
|
||||
|
||||
The `WebHook-Allowed-Rate` header MUST be returned if the request contained the
|
||||
`WebHook-Request-Rate`, otherwise it SHOULD be returned.
|
||||
The `WebHook-Allowed-Rate` header MUST be returned alongside
|
||||
`WebHook-Allowed-Origin`if the request contained the `WebHook-Request-Rate`
|
||||
header, otherwise it SHOULD be returned.
|
||||
|
||||
For the callback model, the `WebHook-Allowed-Rate` header SHOULD be included
|
||||
in the callback request. If the header is not included, for instance when a
|
||||
callback is issued through a browser as a GET request, the allowed rate SHOULD
|
||||
correspond to the requested rate.
|
||||
|
||||
The header grants permission to send notifications at the specified rate. The
|
||||
value is either an asterisk character or the string representation of a positive
|
||||
|
@ -346,7 +349,7 @@ WebHook-Allowed-Rate: 100
|
|||
- [RFC7540][rfc7540] Hypertext Transfer Protocol Version 2 (HTTP/2)
|
||||
|
||||
[ce]: ./spec.md
|
||||
[webhooks]: http://progrium.com/blog/2007/05/03/web-hooks-to-revolutionize-the-web/
|
||||
[webhooks]: https://progrium.github.io/blog/2007/05/03/web-hooks-to-revolutionize-the-web/index.html
|
||||
[content-type]: https://tools.ietf.org/html/rfc7231#section-3.1.1.5
|
||||
[retry-after]: https://tools.ietf.org/html/rfc7231#section-7.1.3
|
||||
[authorization]: https://tools.ietf.org/html/rfc7235#section-4.2
|
|
@ -0,0 +1,2 @@
|
|||
# מפרט CloudEvents - גרסה 1.0.3 -בתהליך כתיבה
|
||||
מסמך זה טרם תורגם. בבקשה תשתמשו [בגרסה האנגלית של המסמך](../../README.md) לבינתיים.
|
|
@ -0,0 +1,2 @@
|
|||
# CloudEvents Release Notes
|
||||
מסמך זה טרם תורגם. בבקשה תשתמשו [בגרסה האנגלית של המסמך](../../RELEASE_NOTES.md) לבינתיים.
|
|
@ -0,0 +1,2 @@
|
|||
# CloudEvents SDK Requirements
|
||||
מסמך זה טרם תורגם. בבקשה תשתמשו [בגרסה האנגלית של המסמך](../../SDK.md) לבינתיים.
|
|
@ -0,0 +1,2 @@
|
|||
# CloudEvents Adapters
|
||||
מסמך זה טרם תורגם. בבקשה תשתמשו [בגרסה האנגלית של המסמך](../../../adapters/README.md) לבינתיים.
|
|
@ -0,0 +1,2 @@
|
|||
# AWS Simple Storage Service CloudEvents Adapter
|
||||
מסמך זה טרם תורגם. בבקשה תשתמשו [בגרסה האנגלית של המסמך](../../../adapters/aws-s3.md) לבינתיים.
|
|
@ -0,0 +1,2 @@
|
|||
# Amazon Simple Notification Service CloudEvents Adapter
|
||||
מסמך זה טרם תורגם. בבקשה תשתמשו [בגרסה האנגלית של המסמך](../../../adapters/aws-sns.md) לבינתיים.
|
|
@ -0,0 +1,2 @@
|
|||
# CouchDB CloudEvents Adapter
|
||||
מסמך זה טרם תורגם. בבקשה תשתמשו [בגרסה האנגלית של המסמך](../../../adapters/couchdb.md) לבינתיים.
|
|
@ -0,0 +1,2 @@
|
|||
# GitHub CloudEvents Adapter
|
||||
מסמך זה טרם תורגם. בבקשה תשתמשו [בגרסה האנגלית של המסמך](../../../adapters/github.md) לבינתיים.
|
|
@ -0,0 +1,2 @@
|
|||
# GitLab CloudEvents Adapter
|
||||
מסמך זה טרם תורגם. בבקשה תשתמשו [בגרסה האנגלית של המסמך](../../../adapters/gitlab.md) לבינתיים.
|
|
@ -0,0 +1,2 @@
|
|||
# AMQP Protocol Binding for CloudEvents - Version 1.0.3-wip
|
||||
מסמך זה טרם תורגם. בבקשה תשתמשו [בגרסה האנגלית של המסמך](../../../bindings/amqp-protocol-binding.md) לבינתיים.
|
|
@ -0,0 +1,2 @@
|
|||
# HTTP Protocol Binding for CloudEvents - Version 1.0.3-wip
|
||||
מסמך זה טרם תורגם. בבקשה תשתמשו [בגרסה האנגלית של המסמך](../../../bindings/http-protocol-binding.md) לבינתיים.
|
|
@ -0,0 +1,2 @@
|
|||
# Kafka Protocol Binding for CloudEvents - Version 1.0.3-wip
|
||||
מסמך זה טרם תורגם. בבקשה תשתמשו [בגרסה האנגלית של המסמך](../../../bindings/kafka-protocol-binding.md) לבינתיים.
|
|
@ -0,0 +1,2 @@
|
|||
# MQTT Protocol Binding for CloudEvents - Version 1.0.3-wip
|
||||
מסמך זה טרם תורגם. בבקשה תשתמשו [בגרסה האנגלית של המסמך](../../../bindings/mqtt-protocol-binding.md) לבינתיים.
|
|
@ -0,0 +1,2 @@
|
|||
# NATS Protocol Binding for CloudEvents - Version 1.0.3-wip
|
||||
מסמך זה טרם תורגם. בבקשה תשתמשו [בגרסה האנגלית של המסמך](../../../bindings/nats-protocol-binding.md) לבינתיים.
|
|
@ -0,0 +1,2 @@
|
|||
# WebSockets Protocol Binding for CloudEvents - Version 1.0.3-wip
|
||||
מסמך זה טרם תורגם. בבקשה תשתמשו [בגרסה האנגלית של המסמך](../../../bindings/websockets-protocol-binding.md) לבינתיים.
|
|
@ -0,0 +1,2 @@
|
|||
# CloudEvents Extension Attributes
|
||||
מסמך זה טרם תורגם. בבקשה תשתמשו [בגרסה האנגלית של המסמך](../../../extensions/README.md) לבינתיים.
|
|
@ -0,0 +1,2 @@
|
|||
# Auth Context
|
||||
מסמך זה טרם תורגם. בבקשה תשתמשו [בגרסה האנגלית של המסמך](../../../extensions/authcontext.md) לבינתיים.
|
|
@ -0,0 +1,2 @@
|
|||
# Business Activity Monitoring (BAM) Extension
|
||||
מסמך זה טרם תורגם. בבקשה תשתמשו [בגרסה האנגלית של המסמך](../../../extensions/bam.md) לבינתיים.
|
|
@ -0,0 +1,7 @@
|
|||
# Correlation
|
||||
|
||||
מסמך זה טרם תורגם. בבקשה תשתמשו [בגרסה האנגלית של המסמך](../../../extensions/correlation.md) לבינתיים.
|
||||
|
||||
אם ברצונכם להציע תרגום לעברית, ניתן לעשות זאת באמצעות [פתיחת issue](https://github.com/cloudevents/spec/issues) בגיטהאב.
|
||||
|
||||
אנו מבקשים מכם להציע תרגום לעברית בלבד, ולא להציע תרגום לאנגלית.
|
|
@ -0,0 +1,2 @@
|
|||
# Data Classification Extension
|
||||
מסמך זה טרם תורגם. בבקשה תשתמשו [בגרסה האנגלית של המסמך](../../../extensions/data-classification.md) לבינתיים.
|
|
@ -0,0 +1,2 @@
|
|||
# Dataref (Claim Check Pattern)
|
||||
מסמך זה טרם תורגם. בבקשה תשתמשו [בגרסה האנגלית של המסמך](../../../extensions/dataref.md) לבינתיים.
|
Some files were not shown because too many files have changed in this diff Show More
Loading…
Reference in New Issue