daifuku 0.9.0
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +7 -0
- data/.github/workflows/ruby.yml +31 -0
- data/.gitignore +56 -0
- data/.ruby-version +1 -0
- data/Gemfile +6 -0
- data/Gemfile.lock +55 -0
- data/LICENSE +21 -0
- data/README.md +149 -0
- data/Rakefile +6 -0
- data/daifuku.gemspec +39 -0
- data/daifuku.rb +9 -0
- data/docs/images/code-completion.png +0 -0
- data/docs/images/transpile.png +0 -0
- data/docs/syntax.ja.md +143 -0
- data/example/LogDefinitions/common.md +20 -0
- data/example/LogDefinitions/recipe_search.md +19 -0
- data/example/iOS/Templates/CommonPayload.swift.erb +25 -0
- data/example/iOS/Templates/LogCategories.swift.erb +33 -0
- data/example/iOS/generate-log-classes.rb +212 -0
- data/lib/daifuku/compiler.rb +43 -0
- data/lib/daifuku/models.rb +171 -0
- data/lib/daifuku/parser.rb +76 -0
- data/lib/daifuku/renderer.rb +11 -0
- data/lib/daifuku/strdef_generator.rb +196 -0
- data/lib/daifuku/validator.rb +127 -0
- data/lib/daifuku/version.rb +3 -0
- data/lib/daifuku.rb +10 -0
- metadata +143 -0
checksums.yaml
ADDED
@@ -0,0 +1,7 @@
|
|
1
|
+
---
|
2
|
+
SHA256:
|
3
|
+
metadata.gz: 1fdf491fb8af78cfb95b601dd4f4fad28a1a4c73003498de29b929206199beb6
|
4
|
+
data.tar.gz: 9efe45238a4ea0ea0ae5d06b88b440f84044c520af425b7e35e5e8f653bbcf10
|
5
|
+
SHA512:
|
6
|
+
metadata.gz: fcaa3cb1c984235e7e383d63896352966ee649bb858b4865faa1c0598335439d2467c8993bd50dcbb07ef69035aa6b21c6d0f7c4cfd0ca8c4f0172dff325af73
|
7
|
+
data.tar.gz: 8de8c756e0264b0cb353b14115fd93a0d7cf3ac787e41eec267c9fb375cd80def016423de3145be69216268738422c95132d71ed97a383a654c2103e5d4a6275
|
@@ -0,0 +1,31 @@
|
|
1
|
+
name: Ruby
|
2
|
+
|
3
|
+
on:
|
4
|
+
push:
|
5
|
+
branches: [ "main" ]
|
6
|
+
pull_request:
|
7
|
+
branches: [ "main" ]
|
8
|
+
|
9
|
+
permissions:
|
10
|
+
contents: read
|
11
|
+
|
12
|
+
jobs:
|
13
|
+
test:
|
14
|
+
|
15
|
+
runs-on: ubuntu-latest
|
16
|
+
strategy:
|
17
|
+
matrix:
|
18
|
+
ruby-version: ['3.1', head]
|
19
|
+
|
20
|
+
steps:
|
21
|
+
- uses: actions/checkout@v3
|
22
|
+
- name: Set up Ruby
|
23
|
+
# To automatically get bug fixes and new Ruby versions for ruby/setup-ruby,
|
24
|
+
# change this to (see https://github.com/ruby/setup-ruby#versioning):
|
25
|
+
# uses: ruby/setup-ruby@v1
|
26
|
+
uses: ruby/setup-ruby@55283cc23133118229fd3f97f9336ee23a179fcf # v1.146.0
|
27
|
+
with:
|
28
|
+
ruby-version: ${{ matrix.ruby-version }}
|
29
|
+
bundler-cache: true # runs 'bundle install' and caches installed gems automatically
|
30
|
+
- name: Run tests
|
31
|
+
run: bundle exec rake
|
data/.gitignore
ADDED
@@ -0,0 +1,56 @@
|
|
1
|
+
*.gem
|
2
|
+
*.rbc
|
3
|
+
/.config
|
4
|
+
/coverage/
|
5
|
+
/InstalledFiles
|
6
|
+
/pkg/
|
7
|
+
/spec/reports/
|
8
|
+
/spec/examples.txt
|
9
|
+
/test/tmp/
|
10
|
+
/test/version_tmp/
|
11
|
+
/tmp/
|
12
|
+
|
13
|
+
# Used by dotenv library to load environment variables.
|
14
|
+
# .env
|
15
|
+
|
16
|
+
# Ignore Byebug command history file.
|
17
|
+
.byebug_history
|
18
|
+
|
19
|
+
## Specific to RubyMotion:
|
20
|
+
.dat*
|
21
|
+
.repl_history
|
22
|
+
build/
|
23
|
+
*.bridgesupport
|
24
|
+
build-iPhoneOS/
|
25
|
+
build-iPhoneSimulator/
|
26
|
+
|
27
|
+
## Specific to RubyMotion (use of CocoaPods):
|
28
|
+
#
|
29
|
+
# We recommend against adding the Pods directory to your .gitignore. However
|
30
|
+
# you should judge for yourself, the pros and cons are mentioned at:
|
31
|
+
# https://guides.cocoapods.org/using/using-cocoapods.html#should-i-check-the-pods-directory-into-source-control
|
32
|
+
#
|
33
|
+
# vendor/Pods/
|
34
|
+
|
35
|
+
## Documentation cache and generated files:
|
36
|
+
/.yardoc/
|
37
|
+
/_yardoc/
|
38
|
+
/doc/
|
39
|
+
/rdoc/
|
40
|
+
|
41
|
+
## Environment normalization:
|
42
|
+
/.bundle/
|
43
|
+
/vendor/bundle
|
44
|
+
/lib/bundler/man/
|
45
|
+
|
46
|
+
# for a library or gem, you might want to ignore these files since the code is
|
47
|
+
# intended to run in multiple environments; otherwise, check them in:
|
48
|
+
# Gemfile.lock
|
49
|
+
# .ruby-version
|
50
|
+
# .ruby-gemset
|
51
|
+
|
52
|
+
# unless supporting rvm < 1.11.0 or doing something fancy, ignore this:
|
53
|
+
.rvmrc
|
54
|
+
|
55
|
+
# Used by RuboCop. Remote config files pulled in from inherit_from directive.
|
56
|
+
# .rubocop-https?--*
|
data/.ruby-version
ADDED
@@ -0,0 +1 @@
|
|
1
|
+
3.2
|
data/Gemfile
ADDED
data/Gemfile.lock
ADDED
@@ -0,0 +1,55 @@
|
|
1
|
+
PATH
|
2
|
+
remote: .
|
3
|
+
specs:
|
4
|
+
daifuku (0.9.0)
|
5
|
+
nokogiri
|
6
|
+
redcarpet
|
7
|
+
|
8
|
+
GEM
|
9
|
+
remote: https://rubygems.org/
|
10
|
+
specs:
|
11
|
+
activesupport-inflector (0.1.0)
|
12
|
+
coderay (1.1.3)
|
13
|
+
concurrent-ruby (1.2.2)
|
14
|
+
diff-lcs (1.5.0)
|
15
|
+
i18n (1.14.1)
|
16
|
+
concurrent-ruby (~> 1.0)
|
17
|
+
method_source (1.0.0)
|
18
|
+
mini_portile2 (2.8.4)
|
19
|
+
nokogiri (1.15.3)
|
20
|
+
mini_portile2 (~> 2.8.2)
|
21
|
+
racc (~> 1.4)
|
22
|
+
pry (0.14.2)
|
23
|
+
coderay (~> 1.1)
|
24
|
+
method_source (~> 1.0)
|
25
|
+
racc (1.7.1)
|
26
|
+
rake (13.0.6)
|
27
|
+
redcarpet (3.6.0)
|
28
|
+
rspec (3.12.0)
|
29
|
+
rspec-core (~> 3.12.0)
|
30
|
+
rspec-expectations (~> 3.12.0)
|
31
|
+
rspec-mocks (~> 3.12.0)
|
32
|
+
rspec-core (3.12.2)
|
33
|
+
rspec-support (~> 3.12.0)
|
34
|
+
rspec-expectations (3.12.3)
|
35
|
+
diff-lcs (>= 1.2.0, < 2.0)
|
36
|
+
rspec-support (~> 3.12.0)
|
37
|
+
rspec-mocks (3.12.6)
|
38
|
+
diff-lcs (>= 1.2.0, < 2.0)
|
39
|
+
rspec-support (~> 3.12.0)
|
40
|
+
rspec-support (3.12.1)
|
41
|
+
|
42
|
+
PLATFORMS
|
43
|
+
ruby
|
44
|
+
|
45
|
+
DEPENDENCIES
|
46
|
+
activesupport-inflector (~> 0.1.0)
|
47
|
+
bundler (~> 2.0)
|
48
|
+
daifuku!
|
49
|
+
i18n
|
50
|
+
pry
|
51
|
+
rake (~> 13.0)
|
52
|
+
rspec (~> 3.0)
|
53
|
+
|
54
|
+
BUNDLED WITH
|
55
|
+
2.4.14
|
data/LICENSE
ADDED
@@ -0,0 +1,21 @@
|
|
1
|
+
MIT License
|
2
|
+
|
3
|
+
Copyright (c) 2023 Cookpad Inc.
|
4
|
+
|
5
|
+
Permission is hereby granted, free of charge, to any person obtaining a copy
|
6
|
+
of this software and associated documentation files (the "Software"), to deal
|
7
|
+
in the Software without restriction, including without limitation the rights
|
8
|
+
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
9
|
+
copies of the Software, and to permit persons to whom the Software is
|
10
|
+
furnished to do so, subject to the following conditions:
|
11
|
+
|
12
|
+
The above copyright notice and this permission notice shall be included in all
|
13
|
+
copies or substantial portions of the Software.
|
14
|
+
|
15
|
+
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
16
|
+
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
17
|
+
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
18
|
+
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
19
|
+
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
20
|
+
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
21
|
+
SOFTWARE.
|
data/README.md
ADDED
@@ -0,0 +1,149 @@
|
|
1
|
+
# daifuku
|
2
|
+
A markdown parser and compiler for log definitions in mobile applications
|
3
|
+
|
4
|
+
## Usage
|
5
|
+
Automatic generation of document-based type-safe log implementation code
|
6
|
+
|
7
|
+
![Transpile](docs/images/transpile.png)
|
8
|
+
|
9
|
+
### Step 1
|
10
|
+
Consider log specifications and write documentation.
|
11
|
+
|
12
|
+
- Syntax: [docs/syntax.ja.md](docs/syntax.ja.md)
|
13
|
+
- Example: [example/LogDefinitions/recipe_search.md](./example/LogDefinitions/recipe_search.md)
|
14
|
+
|
15
|
+
#### Log definition documents (Markdown)
|
16
|
+
|
17
|
+
```md
|
18
|
+
# recipe_search
|
19
|
+
|
20
|
+
An category of events related to recipe search.
|
21
|
+
|
22
|
+
## search
|
23
|
+
|
24
|
+
An event sent when users perform a recipe search.
|
25
|
+
|
26
|
+
- keyword: !string 256
|
27
|
+
- Search keyword
|
28
|
+
- order: SearchOrder
|
29
|
+
- latest, popularity
|
30
|
+
|
31
|
+
## show_recipe
|
32
|
+
|
33
|
+
An event sent when users move from the search results screen to the recipe details screen.
|
34
|
+
|
35
|
+
- recipe_id: !integer
|
36
|
+
- ID of the selected recipe
|
37
|
+
|
38
|
+
```
|
39
|
+
|
40
|
+
### Step 2
|
41
|
+
|
42
|
+
Run the script.
|
43
|
+
|
44
|
+
- Example: [example/iOS/generate-log-classes.rb](./example/iOS/generate-log-classes.rb)
|
45
|
+
|
46
|
+
```sh
|
47
|
+
bundle install
|
48
|
+
ruby example/iOS/generate-log-classes.rb
|
49
|
+
```
|
50
|
+
|
51
|
+
After that, the following `.swift` files will be automatically generated.
|
52
|
+
|
53
|
+
```sh
|
54
|
+
ls example/AutoGenerated
|
55
|
+
# CommonPayload.swift LogCategories.swift
|
56
|
+
```
|
57
|
+
|
58
|
+
#### Log definition code (Swift)
|
59
|
+
|
60
|
+
```swift
|
61
|
+
/// Events on the recipe search screen
|
62
|
+
public enum RecipeSearch: LogCategory {
|
63
|
+
/// An event sent when users perform a recipe search.
|
64
|
+
case search(keyword: String, order: SearchOrder)
|
65
|
+
/// An event sent when users move from the search results screen to the recipe details screen.
|
66
|
+
case showRecipe(recipeId: Int64)
|
67
|
+
}
|
68
|
+
```
|
69
|
+
|
70
|
+
### Step 3
|
71
|
+
|
72
|
+
Send logs with the enums of the log definition.
|
73
|
+
|
74
|
+
#### Log implementation code (Swift)
|
75
|
+
|
76
|
+
```swift
|
77
|
+
// After the search request
|
78
|
+
logger.post(
|
79
|
+
RecipeSearch.search(
|
80
|
+
keyword: keyword, // “egg"
|
81
|
+
order: order // .latest
|
82
|
+
)
|
83
|
+
)
|
84
|
+
```
|
85
|
+
|
86
|
+
## What makes you happy?
|
87
|
+
|
88
|
+
### Fully documented at all times
|
89
|
+
Because of the way it works, you cannot implement logging without writing documentation. This means that there will always be documentation.
|
90
|
+
|
91
|
+
Happy implementers and happy analysts 😊
|
92
|
+
|
93
|
+
### Type safety
|
94
|
+
#### No unintended values are introduced
|
95
|
+
|
96
|
+
Because the possible values, such as character limits, patterns, and numeric ranges, are guaranteed at the type level, it prevents unintended values from entering the log database.
|
97
|
+
|
98
|
+
#### Comfortable to be complemented by IDE
|
99
|
+
|
100
|
+
Completion during implementation also improves the development experience and reduces mistakes.
|
101
|
+
|
102
|
+
![Code Completion](docs/images/code-completion.png)
|
103
|
+
|
104
|
+
### Easy to read for both humans and machines
|
105
|
+
|
106
|
+
Markdown is excellent as a format for log definition documents that anyone could easily read and write.
|
107
|
+
|
108
|
+
In addition, it was useful to be able to statically analyze both the definition document and the implementation.
|
109
|
+
|
110
|
+
For example, mistakes such as "I defined it in the document but forgot to implement it" could be detected automatically.
|
111
|
+
|
112
|
+
This mechanism has actually been useful several times in regular CI runs.
|
113
|
+
(It was also useful to be able to notice when a log was accidentally deleted during refactoring, etc.).
|
114
|
+
|
115
|
+
## Case Study
|
116
|
+
|
117
|
+
### Git version control in the same repository as the app
|
118
|
+
In Cookpad (Japan), log definitions and mobile application source code are managed in the same git repository.
|
119
|
+
|
120
|
+
#### Everything in one place (easy to find)
|
121
|
+
It is all in one place, so there is no need to wander around looking for information in logs.
|
122
|
+
|
123
|
+
#### Background of log definitions can also be checked by following pull requests
|
124
|
+
|
125
|
+
It is also possible to run `git blame` on log markdown definitions and follow pull requests to find out which version of the log was added, who implemented the log, and with what intention.
|
126
|
+
|
127
|
+
|
128
|
+
## Articles (Japanese)
|
129
|
+
- ドキュメントベースの型安全なモバイルアプリ行動ログ基盤の構築 - クックパッド開発者ブログ https://techlife.cookpad.com/entry/2020/11/05/110000
|
130
|
+
- モバイルアプリの行動ログの「仕込み」を快適にする https://speakerdeck.com/yujif/iosdc-japan-2022-mobile-app-logging
|
131
|
+
|
132
|
+
## Original Author
|
133
|
+
[@giginet](https://github.com/giginet)
|
134
|
+
|
135
|
+
## Contributors
|
136
|
+
[@hiragram](https://github.com/hiragram)
|
137
|
+
[@litmon](https://github.com/litmon)
|
138
|
+
[@ksfee684](https://github.com/ksfee684)
|
139
|
+
[@aamine](https://github.com/aamine)
|
140
|
+
[@vincentisambart](https://github.com/vincentisambart)
|
141
|
+
[@kalupas226](https://github.com/kalupas226)
|
142
|
+
[@yujif](https://github.com/yujif)
|
143
|
+
|
144
|
+
## Contributing
|
145
|
+
This repo is basically *read-only*. We publish this code for knowledge sharing purposes.
|
146
|
+
Please note that we cannot guarantee continuous maintenance or responses to Issues or Pull Requests.
|
147
|
+
|
148
|
+
## License
|
149
|
+
MIT License
|
data/Rakefile
ADDED
data/daifuku.gemspec
ADDED
@@ -0,0 +1,39 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
lib = File.expand_path("lib", __dir__)
|
4
|
+
$LOAD_PATH.unshift(lib) unless $LOAD_PATH.include?(lib)
|
5
|
+
require "daifuku/version"
|
6
|
+
|
7
|
+
Gem::Specification.new do |spec|
|
8
|
+
spec.name = "daifuku"
|
9
|
+
spec.version = Daifuku::VERSION
|
10
|
+
spec.authors = ["Kohki Miki"]
|
11
|
+
spec.email = ["giginet.net@gmail.com"]
|
12
|
+
|
13
|
+
spec.summary = "A markdown parser and compiler for log definitions in mobile applications"
|
14
|
+
spec.description = <<~EOF
|
15
|
+
Daifuku is a markdown parser and compiler for log definitions in mobile applications. It provides an
|
16
|
+
automatic generation of document-based type-safe log implementation code from markdown.
|
17
|
+
EOF
|
18
|
+
spec.homepage = "https://github.com/cookpad/daifuku"
|
19
|
+
spec.license = 'MIT'
|
20
|
+
|
21
|
+
spec.metadata["homepage_uri"] = spec.homepage
|
22
|
+
spec.metadata["source_code_uri"] = spec.homepage
|
23
|
+
|
24
|
+
# Specify which files should be added to the gem when it is released.
|
25
|
+
# The `git ls-files -z` loads the files in the RubyGem that have been added into git.
|
26
|
+
spec.files = Dir.chdir(File.expand_path('..', __FILE__)) do
|
27
|
+
`git ls-files -z`.split("\x0").reject { |f| f.match(%r{^(test|spec|features)/}) }
|
28
|
+
end
|
29
|
+
spec.bindir = "exe"
|
30
|
+
spec.executables = spec.files.grep(%r{^exe/}) { |f| File.basename(f) }
|
31
|
+
spec.require_paths = ["lib"]
|
32
|
+
|
33
|
+
spec.add_dependency "redcarpet", "~> 3.6"
|
34
|
+
spec.add_dependency "nokogiri", "~> 1.15"
|
35
|
+
|
36
|
+
spec.add_development_dependency "bundler", "~> 2.0"
|
37
|
+
spec.add_development_dependency "rake", "~> 13.0"
|
38
|
+
spec.add_development_dependency "rspec", "~> 3.0"
|
39
|
+
end
|
data/daifuku.rb
ADDED
Binary file
|
Binary file
|
data/docs/syntax.ja.md
ADDED
@@ -0,0 +1,143 @@
|
|
1
|
+
# daifuku ログ定義用 Markdown 形式
|
2
|
+
|
3
|
+
## 要素
|
4
|
+
ログは**カテゴリ**、**イベント**、**カラム**の3要素からなります。
|
5
|
+
|
6
|
+
- カテゴリ:イベントの集合。近しい機能を同一のカテゴリとして扱う(`RecipeSearch`など)
|
7
|
+
- イベント:ログを送るきっかけとなる動作単位
|
8
|
+
- カラム:イベントの持つ値。型と名前を持つ
|
9
|
+
|
10
|
+
それぞれの名前は `/\w+/` であることが期待されています。
|
11
|
+
|
12
|
+
# ログ定義の記述
|
13
|
+
|
14
|
+
```markdown
|
15
|
+
# recipe_search
|
16
|
+
|
17
|
+
レシピ検索に関するログです。
|
18
|
+
|
19
|
+
## search
|
20
|
+
|
21
|
+
ユーザーがレシピをキーワード検索したときに送信されます。
|
22
|
+
|
23
|
+
- keyword: !string 256
|
24
|
+
- 検索キーワード
|
25
|
+
- order: SearchOrder
|
26
|
+
- 新着順, 人気順
|
27
|
+
|
28
|
+
## show_recipe
|
29
|
+
|
30
|
+
ユーザーが検索結果画面でレシピを選択したときに送信されます。
|
31
|
+
|
32
|
+
- recipe_id: !integer
|
33
|
+
- 選択されたレシピのID
|
34
|
+
- position: !integer
|
35
|
+
- タップしたクエリが上から何番目か (0始まり)
|
36
|
+
```
|
37
|
+
|
38
|
+
## カテゴリ
|
39
|
+
|
40
|
+
ドキュメントのトップレベルに記述した文章は全てカテゴリの説明として扱われます。
|
41
|
+
|
42
|
+
文中のインライン要素は十分にテストされていません。
|
43
|
+
**文章の記述にはボールドやコードブロックなどのインライン要素を使わない方が無難です。**
|
44
|
+
|
45
|
+
**仕様上はカテゴリ共通カラムの定義が可能ですが、現段階では未対応です。**
|
46
|
+
|
47
|
+
ファイル名がカテゴリ名として扱われますが、分かりやすさのために、`#` 見出しをファイル名と同じにしましょう。`snake_case`が推奨されます。
|
48
|
+
|
49
|
+
## イベント
|
50
|
+
|
51
|
+
`##` 見出し以下の文章はイベントの説明、カラム定義はイベント内のカラムとして扱われます。
|
52
|
+
|
53
|
+
見出しがイベント名として扱われます。`snake_case`が推奨されます。
|
54
|
+
|
55
|
+
## カラム
|
56
|
+
|
57
|
+
イベント以下にあるリスト要素はカラムとして扱われます。カラムは以下のようなシンタックスで定義できます。
|
58
|
+
|
59
|
+
```markdown
|
60
|
+
- <カラム名>: !<カラム型>(?)
|
61
|
+
- カラムの説明1
|
62
|
+
- カラムの説明2
|
63
|
+
```
|
64
|
+
|
65
|
+
### 型
|
66
|
+
|
67
|
+
- `!`から始まる型はプリミティブ型です。
|
68
|
+
- 末尾に`?`をつけることでオプショナル型として定義することができます。
|
69
|
+
- 未知の型を利用したとき、生成に失敗します。
|
70
|
+
|
71
|
+
クックパッドでは データウェアハウス に Amazon Redshift を利用しており、[Redshift でサポートされているデータ型](https://docs.aws.amazon.com/redshift/latest/dg/c_Supported_data_types.html)を前提として以下の利用可能な型を定義しています。
|
72
|
+
|
73
|
+
- !smallint : 16ビット符号付き整数
|
74
|
+
- !integer : 32ビット符号付き整数
|
75
|
+
- !bigint : 64ビット符号付き整数
|
76
|
+
- !real : 32ビット浮動小数点数
|
77
|
+
- !double : 64ビット浮動小数点数
|
78
|
+
- !boolean : 真偽値
|
79
|
+
- !string <バイト数> : 文字列型
|
80
|
+
- !date : 日付型
|
81
|
+
- !timestamp : 日付時刻型(タイムゾーンなし)
|
82
|
+
- !timestamptz : 日付時刻型(タイムゾーンあり)
|
83
|
+
|
84
|
+
|
85
|
+
文字列型は定義時に文字列長の指定が可能です。
|
86
|
+
|
87
|
+
```markdown
|
88
|
+
- message: !string 256
|
89
|
+
```
|
90
|
+
|
91
|
+
|
92
|
+
### カスタム型
|
93
|
+
|
94
|
+
カスタム型を定義、利用することもできます。
|
95
|
+
アプリケーション側で enum などを定義して特定の定義域を表現するのに利用できます。
|
96
|
+
|
97
|
+
ログ定義側でカスタム型を利用するには、`!`から始まらない型名を直接指定してください。
|
98
|
+
|
99
|
+
```markdown
|
100
|
+
# user
|
101
|
+
|
102
|
+
## set_profile
|
103
|
+
|
104
|
+
- user_status: UserStatus
|
105
|
+
- ユーザー状態
|
106
|
+
```
|
107
|
+
|
108
|
+
### obsolete指定
|
109
|
+
|
110
|
+
利用しなくなったイベントやカラムには `[obsolete]` 指定が使えます。これを含んだイベントやカラムはコード生成から除外されますが、古いログの調査のためにドキュメントには残ります。
|
111
|
+
|
112
|
+
descriptionに使用できなくなったアプリのバージョン名を明記しておくと便利です。
|
113
|
+
|
114
|
+
```markdown
|
115
|
+
- [obsolete] user_status: UserStatus
|
116
|
+
- ユーザー状態
|
117
|
+
- v2020.34.0 から廃止されました
|
118
|
+
```
|
119
|
+
|
120
|
+
# CommonPayload
|
121
|
+
|
122
|
+
すべてのイベントが共通して持つカラムを`CommonPayload`と呼んでいます。
|
123
|
+
これはUser AgentやユーザーID、OSバージョンなどを想定しています。
|
124
|
+
|
125
|
+
`common`というカテゴリ名のログ定義は特別に`CommonPayload`として扱われます。
|
126
|
+
すなわち、`LogDefinitions/common.md`にカラムを記述することで、`CommonPayload`として処理されます。
|
127
|
+
|
128
|
+
記述方法は普通のカテゴリと同様ですが、トップレベルのカラムだけがパースされ、イベント定義は無視されます。
|
129
|
+
|
130
|
+
```markdown
|
131
|
+
# common
|
132
|
+
|
133
|
+
- user_id: !bigint?
|
134
|
+
- ユーザーID
|
135
|
+
- user_agent: !string 1000
|
136
|
+
- ユーザーエージェント
|
137
|
+
- os_version: !string 32
|
138
|
+
- iOSバージョン
|
139
|
+
- application_version: !string 32
|
140
|
+
- アプリケーションバージョン
|
141
|
+
- time_zone: !string 64
|
142
|
+
- タイムゾーン(Asia/Tokyoなど)
|
143
|
+
```
|
@@ -0,0 +1,20 @@
|
|
1
|
+
# common
|
2
|
+
|
3
|
+
- user_id: !bigint?
|
4
|
+
- ユーザーID
|
5
|
+
- user_agent: !string 1000
|
6
|
+
- ユーザーエージェント
|
7
|
+
- os_version: !string 32
|
8
|
+
- iOSバージョン
|
9
|
+
- application_version: !string 32
|
10
|
+
- アプリケーションバージョン
|
11
|
+
- time_zone: !string 64
|
12
|
+
- タイムゾーン(Asia/Tokyoなど)
|
13
|
+
- [obsolete] user_status: !string 32
|
14
|
+
- example1, example2, example3
|
15
|
+
- device_kind: DeviceKind
|
16
|
+
- 端末の種類
|
17
|
+
- phone, tablet, unknown
|
18
|
+
- device_model: !string 16
|
19
|
+
- 端末のモデル
|
20
|
+
- 実機だと「iPhoneXX,X」または「iPadXX.X」形式
|
@@ -0,0 +1,19 @@
|
|
1
|
+
# recipe_search
|
2
|
+
|
3
|
+
An category of events related to recipe search.
|
4
|
+
|
5
|
+
## search
|
6
|
+
|
7
|
+
An event sent when users perform a recipe search.
|
8
|
+
|
9
|
+
- keyword: !string 256
|
10
|
+
- Search keyword
|
11
|
+
- order: SearchOrder
|
12
|
+
- latest, popularity
|
13
|
+
|
14
|
+
## show_recipe
|
15
|
+
|
16
|
+
Sent when users move from the search results screen to the recipe details screen.
|
17
|
+
|
18
|
+
- recipe_id: !integer
|
19
|
+
- ID of the selected recipe
|
@@ -0,0 +1,25 @@
|
|
1
|
+
import Foundation
|
2
|
+
|
3
|
+
// This file is automatically generated by generate-log-classes.
|
4
|
+
public struct CommonPayload {
|
5
|
+
<%- columns.each do |column| -%>
|
6
|
+
<%- column.descriptions.flat_map(&:lines).each do |description_line| -%>
|
7
|
+
/// <%= description_line.strip %>
|
8
|
+
<%- end -%>
|
9
|
+
var <%= column.variable_name %>: <%= column.swift_type %>
|
10
|
+
<%- end -%>
|
11
|
+
|
12
|
+
public func makePayload() -> [String: JSONCodable] {
|
13
|
+
return [
|
14
|
+
<%- columns.each do |column| -%>
|
15
|
+
"<%= column.original_name %>": <%= column.call_dump %>,
|
16
|
+
<%- end -%>
|
17
|
+
].compactMapValues { $0 }
|
18
|
+
}
|
19
|
+
|
20
|
+
public init(<%= columns.map { |column| column.as_argument }.join(', ') -%>) {
|
21
|
+
<%- columns.each do |column| -%>
|
22
|
+
self.<%= column.variable_name %> = <%= column.variable_name %>
|
23
|
+
<%- end -%>
|
24
|
+
}
|
25
|
+
}
|
@@ -0,0 +1,33 @@
|
|
1
|
+
// This file is automatically generated by generate-log-classes.
|
2
|
+
import Foundation
|
3
|
+
<%- categories.each do |category| -%>
|
4
|
+
<%- category.descriptions.flat_map(&:lines).each do |description_line| -%>
|
5
|
+
/// <%= description_line.strip %>
|
6
|
+
<%- end -%>
|
7
|
+
public enum <%= category.class_name %> {
|
8
|
+
public static var categoryName: String { "<%= category.name %>" }
|
9
|
+
public var eventName: String {
|
10
|
+
<%- if category.available_events.empty? -%>
|
11
|
+
assertionFailure("No events are available in category <%= category.class_name %>")
|
12
|
+
return ""
|
13
|
+
<%- else -%>
|
14
|
+
switch self {
|
15
|
+
<%- category.available_events.each do |event| -%>
|
16
|
+
case .<%= event.variable_name %>: return "<%= event.name %>"
|
17
|
+
<%- end -%>
|
18
|
+
}
|
19
|
+
<%- end -%>
|
20
|
+
}
|
21
|
+
|
22
|
+
<%- category.events.each do |event| -%>
|
23
|
+
<%- event.descriptions.flat_map(&:lines).each do |description_line| -%>
|
24
|
+
/// <%= description_line.strip %>
|
25
|
+
<%- end -%>
|
26
|
+
<%- if event.columns.empty? -%>
|
27
|
+
<%= event.availability_annotation %>case <%= event.variable_name %>
|
28
|
+
<%- else -%>
|
29
|
+
<%= event.availability_annotation %>case <%= event.variable_name %>(<%= event.associated_types %>)
|
30
|
+
<%- end -%>
|
31
|
+
<%- end -%>
|
32
|
+
}
|
33
|
+
<%- end -%>
|